home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Examples / Calc / UCalc.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  103.9 KB  |  3,358 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UCalc.cp
  3. // Copyright © 1985-96 by Apple Computer, Inc. All rights reserved. 
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UCALC__
  7. #include "UCalc.h"
  8. #endif
  9.  
  10. // Calc
  11.  
  12. #ifndef __UCALCROWS__
  13. #include "UCalcRows.h" 
  14. #endif
  15.  
  16. #ifndef __UCALCCOLUMNS__
  17. #include "UCalcColumns.h"
  18. #endif
  19.  
  20. #ifndef __UCALCCELLS__
  21. #include "UCalcCells.h"
  22. #endif
  23.  
  24. // MacApp
  25.  
  26. #ifndef __UDEBUG__
  27. #include "UDebug.h"
  28. #endif
  29.  
  30. #ifndef __USECTIONMGR__
  31. #include "USectionMgr.h"
  32. #endif
  33.  
  34. #ifndef __UVIEWSERVER__
  35. #include "UViewServer.h"
  36. #endif
  37.  
  38. // Toolbox
  39.  
  40. #ifndef __ERRORS__
  41. #include <Errors.h>
  42. #endif
  43.  
  44. #ifndef __QUICKDRAW__
  45. #include <Quickdraw.h>
  46. #endif
  47.  
  48. #ifndef __RESOURCES__
  49. #include <Resources.h>
  50. #endif
  51.  
  52. // ANSI
  53.  
  54. #ifndef __STDIO__
  55. #include <stdio.h>
  56. #endif
  57.  
  58. #ifndef __STDLIB__
  59. #include <stdlib.h>
  60. #endif
  61.  
  62. //----------------------------------------------------------------------------------------
  63. // Global variable definitions.
  64. //----------------------------------------------------------------------------------------
  65.  
  66. ValueFormat        gGeneralFormat;                // SANE conversion formats 
  67. ValueFormat        gDecimalFormat;
  68. ValueFormat        gNoDecimalFormat;
  69. ValueFormat        gScientificFormat;
  70. ValueFormat        gNoFormat;
  71. FormatRecord    gDefaultFormat;                // default cell format 
  72.  
  73. Pattern            gColumnSeparatorPattern;    // patterns for separator lines 
  74. Pattern            gRowSeparatorPattern;
  75.  
  76.  
  77. //----------------------------------------------------------------------------------------
  78. // ReadCellCoordinate: 
  79. //----------------------------------------------------------------------------------------
  80. #pragma segment AReadFile
  81.  
  82. void ReadCellCoordinate(TFile*            aFile,
  83.                         RowNumber&        r,
  84.                         ColumnNumber&    c)
  85. {
  86.     // Reads a cell coordinate from a file 
  87.  
  88.     CPoint cellCoordinate;
  89.     long count;
  90.  
  91.  
  92.     count = sizeof(CPoint);
  93.     FailOSErr(aFile->ReadData(&cellCoordinate, count));
  94.     r = cellCoordinate.v;
  95.     c = cellCoordinate.h;
  96. } // ReadCellCoordinate 
  97.  
  98.  
  99.  
  100. //========================================================================================
  101. // CLASS TCalcApplication
  102. //========================================================================================
  103. #undef Inherited
  104. #define Inherited TApplication
  105.  
  106. #pragma segment ClassDescRes
  107. MA_DEFINE_CLASS_M1(TCalcApplication, Inherited);
  108.  
  109. //----------------------------------------------------------------------------------------
  110. // TCalcApplication destructor
  111. //----------------------------------------------------------------------------------------
  112. #pragma segment MADestructorRes
  113.  
  114. TCalcApplication::~TCalcApplication()
  115. {
  116. }
  117.  
  118. //----------------------------------------------------------------------------------------
  119. // TCalcApplication::ICalcApplication: 
  120. //----------------------------------------------------------------------------------------
  121. #pragma segment AInit
  122.  
  123. void TCalcApplication::ICalcApplication()
  124.  
  125. {
  126.     IApplication(kFileType, kSignature);
  127.  
  128.     gGeneralFormat.style = FLOATDECIMAL;
  129.     gGeneralFormat.digits = kValuePrecision;
  130.  
  131.     gDecimalFormat.style = FIXEDDECIMAL;
  132.     gDecimalFormat.digits = 2;
  133.  
  134.     gNoDecimalFormat.style = FIXEDDECIMAL;
  135.     gNoDecimalFormat.digits = 0;
  136.  
  137.     gScientificFormat.style = FLOATDECIMAL;
  138.     gScientificFormat.digits = 2;
  139.  
  140.     gNoFormat.style = FIXEDDECIMAL;
  141.     gNoFormat.digits = -1;
  142.  
  143.     gDefaultFormat.fJustification = kDefaultJustification;
  144.     gDefaultFormat.fStyle = kGeneral;
  145.     gDefaultFormat.fDigits = 0;
  146.     gDefaultFormat.fFontNumber = kCellFont;
  147.     gDefaultFormat.fFontSize = kCellFontSize;
  148.     gDefaultFormat.fFontStyle = 0;
  149.  
  150.     gColumnSeparatorPattern = qd.gray;
  151.     gRowSeparatorPattern = qd.gray; 
  152.  
  153.     // Suppress Linker dead-stripping of these classes 
  154.     MA_REGISTER_CLASS(TCalcWindow);
  155.     MA_REGISTER_CLASS(TCellsView);
  156.     MA_REGISTER_CLASS(TRowsView);
  157.     MA_REGISTER_CLASS(TColumnsView);
  158.     MA_REGISTER_CLASS(TEntryView);
  159.     MA_REGISTER_CLASS(TCoordView);
  160.     MA_REGISTER_CLASS(TPrimaryScroller);
  161.     MA_REGISTER_CLASS(TRegionDesignator);
  162.     MA_REGISTER_CLASS(TSecondaryScroller);
  163. } // TCalcApplication::ICalcApplication 
  164.  
  165. //----------------------------------------------------------------------------------------
  166. // TCalcApplication::AboutToLoseControl: Remove Edit menu buzzwords for incoming Desk
  167. // Accessory
  168. //----------------------------------------------------------------------------------------
  169. #pragma segment ADoCommand
  170.  
  171. void TCalcApplication::AboutToLoseControl(Boolean convertClipboard)// override 
  172. {
  173.     SetEditCommandName(cCut, cStandardCut);
  174.     SetEditCommandName(cCopy, cStandardCopy);
  175.     SetEditCommandName(cClear, cStandardClear);
  176.  
  177.     Inherited::AboutToLoseControl(convertClipboard);
  178. } // TCalcApplication::AboutToLoseControl 
  179.  
  180. //----------------------------------------------------------------------------------------
  181. // TCalcApplication::DoMakeDocument: 
  182. //----------------------------------------------------------------------------------------
  183. #pragma segment AOpen
  184.  
  185. TDocument* TCalcApplication::DoMakeDocument(CommandNumber /*itsCommandNumber*/, TFile* itsFile)
  186. {
  187.     TCalcDocument* aCalcDocument = new TCalcDocument;
  188.     
  189.     CRect dimensions(1, 1, kMaxColumns, kMaxRows);
  190.  
  191.     aCalcDocument->ICalcDocument(itsFile, dimensions);
  192.  
  193.     return aCalcDocument;
  194. } // TCalcApplication::DoMakeDocument 
  195.  
  196. //----------------------------------------------------------------------------------------
  197. // TCalcApplication::MakeViewForAlienClipboard: Launch a view to represent the data found
  198. // in the Clipboard at application start-up time, or when returning from an excursion to
  199. // MultiFinder, or when returning from a Desk Accessory. This creates a clipboard for
  200. // 'CALC' scrap.
  201. //----------------------------------------------------------------------------------------
  202. #pragma segment AClipboard
  203.  
  204. TView* TCalcApplication::MakeViewForAlienClipboard()// override 
  205. {
  206.     Handle calcScrap;
  207.     long scrapOffset;
  208.     TCalcDocument * clipDocument;
  209.     TCellsView * clipView;
  210.     ScrapInfoRecord scrapInfo;
  211.     RowNumber r;
  212.     ColumnNumber c;
  213.     short i;
  214.     short cellsRead;
  215.     CPoint cellCoord;
  216.     long offset;
  217.     TRow * aRow;
  218.     TColumn * aColumn;
  219.     TCell * aCell;
  220.     Boolean perm;
  221.  
  222.     // Before doing anything else, make sure the scrap contains my type 
  223.     if (GetScrap(NULL, kCalcScrapType, &offset) > 0)
  224.     {
  225.         clipDocument = NULL;                    // so failure handler knows to free it 
  226.         calcScrap = NULL;
  227.  
  228.         FailInfo fi;
  229.  
  230.         Try(fi)
  231.         {
  232.  
  233.             calcScrap = NewPermHandle(0);
  234.  
  235.             perm = PermAllocation(TRUE);
  236.             scrapOffset = GetScrap(calcScrap, kCalcScrapType, &offset);
  237.             perm = PermAllocation(perm);
  238.  
  239.             // Only a negative result indicates an error--FailOSErr considers any non-zero result an error. 
  240.             if (scrapOffset < 0)
  241.                 FailOSErr((short)scrapOffset);
  242.             scrapOffset = 0;
  243.  
  244.             ReadScrap(calcScrap, scrapOffset, (unsigned char*) & scrapInfo, sizeof(scrapInfo));
  245.             FailMemError();
  246.             clipDocument = new TCalcDocument;
  247.             clipDocument->ICalcDocument(NULL, scrapInfo.selection);
  248.             clipDocument->DoInitialState();
  249.  
  250.             // update the user selection to represent the actual selection in the scrap
  251.             TRegionDesignator * userSelection = (TRegionDesignator *)clipDocument->GetUserSelection();
  252.             if (userSelection)
  253.                 userSelection->SetDesignationRect(scrapInfo.selection);
  254.  
  255.             clipView = NULL;
  256.             clipView = new TCellsView;
  257.             clipView->ICellsView(clipDocument, TRUE, NULL);
  258.             clipDocument->fCellsView = clipView;
  259.  
  260.             for (r = 1; r <= (clipDocument->fNoOfRows); r++)
  261.             {
  262.                 aRow = new TRow;
  263.                 aRow->IRow(r);
  264.                 aRow->ReadFromScrap(calcScrap, scrapOffset);
  265.                 clipDocument->AddRow(aRow);
  266.             }
  267.  
  268.             for (c = 1; c <= (clipDocument->fNoOfColumns); c++)
  269.             {
  270.                 aColumn = new TColumn;
  271.                 aColumn->IColumn(c);
  272.                 aColumn->ReadFromScrap(calcScrap, scrapOffset);
  273.                 clipDocument->AddColumn(aColumn);
  274.             }
  275.  
  276.             cellsRead = 0;
  277.             for (i = 1; i <= (scrapInfo.noOfCells); i++)
  278.             {
  279.                 ReadScrap(calcScrap, scrapOffset, (unsigned char*) & cellCoord, sizeof(cellCoord));
  280.                 aCell = clipDocument->GetCell(cellCoord.v, cellCoord.h);
  281.                 aCell->ReadFromScrap(calcScrap, scrapOffset);
  282.                 cellsRead = cellsRead + 1;
  283.             }
  284.  
  285. #if qDebug
  286.             if (gIntenseDebugging)
  287.             {
  288.                 fprintf(stderr, "MakeViewForAlienClipboard: cellsRead=%d scrapInfo.noOfCells=%d\n", cellsRead, scrapInfo.noOfCells);
  289.                 if (cellsRead != scrapInfo.noOfCells)
  290.                     ProgramBreak("MakeViewForAlienClipboard: Wrong number of cells");
  291.             }
  292. #endif
  293.  
  294.             calcScrap = DisposeIfHandle(calcScrap);
  295.  
  296.             fi.Success();
  297.             return clipView;
  298.         }
  299.         //end of Try
  300.         else
  301.         {                                        //We Failed somewhere along the line
  302.             calcScrap = DisposeIfHandle(calcScrap);
  303.             clipDocument = (TCalcDocument *)(FreeIfObject(clipDocument));
  304.  
  305.             fi.ReSignal();
  306.             
  307.             return NULL;    // this statement is never executed, but it does defeat
  308.                             // an xlC warning
  309.         }
  310.     }
  311.     else
  312.         return Inherited::MakeViewForAlienClipboard();
  313. } // TCalcApplication::MakeViewForAlienClipboard 
  314.  
  315.  
  316. //========================================================================================
  317. // CLASS TCalcDocument
  318. //========================================================================================
  319. #undef Inherited
  320. #define Inherited TEditionDocument
  321.  
  322. #pragma segment ClassDescRes
  323. MA_DEFINE_CLASS_M1(TCalcDocument, Inherited);
  324.  
  325. //----------------------------------------------------------------------------------------
  326. // TCalcDocument::TCalcDocument: 
  327. //----------------------------------------------------------------------------------------
  328. #pragma segment AOpen
  329.  
  330. TCalcDocument::TCalcDocument()
  331. {
  332.     fCellsView = NULL;
  333.     fRowsView = NULL;
  334.     fColumnsView = NULL;
  335.     fEntryView = NULL;
  336.     fCoordView = NULL;
  337.  
  338.     fEditRow = 0;
  339.     fEditColumn = 0;
  340.     fEditCell = NULL;
  341.     
  342.     fRows = NULL;
  343.     fColumns = NULL;
  344.     fCells = NULL;
  345. } // TCalcDocument::TCalcDocument 
  346.  
  347.  
  348. //----------------------------------------------------------------------------------------
  349. // TCalcDocument::ICalcDocument: 
  350. //----------------------------------------------------------------------------------------
  351. #pragma segment AOpen
  352.  
  353. void TCalcDocument::ICalcDocument(TFile* itsFile,
  354.                                   const CRect& dimensions)
  355. {
  356.     CRect aRect;
  357.     TRowList * aRowList;
  358.     TColumnList * aColumnList;
  359.     TCellList * aCellList;
  360.     TRegionDesignator * aRgnDesignator;
  361.     RgnHandle aRgnHandle;
  362.  
  363.     this->IEditionDocument(itsFile, kCalcScrapType, kSignature);
  364.     
  365.     FailInfo fi;
  366.     Try(fi)
  367.     {
  368.         fSavePrintInfo = TRUE;                        // the 'print info' record of the
  369.                                                     // fDocPrintHandler will be written out to
  370.                                                     // the data fork
  371.     
  372.         fDimensions = dimensions;
  373.     
  374.         fRowOffset = dimensions.top - 1;
  375.         fColumnOffset = dimensions.left - 1;
  376.         fNoOfRows = dimensions.bottom - dimensions.top + 1;
  377.         fNoOfColumns = dimensions.right - dimensions.left + 1;
  378.         fCalcMode = kCalcMode;
  379.         fSelectionType = kNoSelection;
  380.     
  381.         fDependencies = new TStandardDependencySpace;
  382.         fDependencies->IStandardDependencySpace();
  383.         
  384.         aRowList = new TRowList;
  385.         aRowList->IRowList();
  386.         fRows = aRowList;
  387.     
  388.         aColumnList = new TColumnList;
  389.         aColumnList->IColumnList();
  390.         fColumns = aColumnList;
  391.     
  392.         aCellList = new TCellList;
  393.         aCellList->ICellList();
  394.         fCells = aCellList;
  395.     
  396.         SetRect(aRect, 1, 1, 1, 1);
  397.         fInUseBounds = aRect;
  398.     
  399.         // create the user selection 
  400.         aRgnHandle = MakeNewRgn();
  401.         aRgnDesignator = new TRegionDesignator;
  402.         aRgnDesignator->IRegionDesignator(aRgnHandle, TRUE);
  403.         aRgnDesignator->SetDesignationRect(CRect(1, 1, 2, 2));
  404.         SetUserSelection(aRgnDesignator);
  405.         fi.Success();
  406.     }
  407.     else
  408.     {
  409.         this->Free();
  410.         fi.ReSignal();
  411.     }
  412. } // TCalcDocument::ICalcDocument 
  413.  
  414.  
  415. //----------------------------------------------------------------------------------------
  416. // TCalcDocument::DoInitialState: 
  417. //----------------------------------------------------------------------------------------
  418. #pragma segment AOpen
  419.  
  420. void TCalcDocument::DoInitialState()    // override 
  421. {
  422.     fAllocatedCells = 0;
  423.     fAllocatedRows = 0;
  424.     fAllocatedColumns = 0;
  425. } // TCalcDocument::DoInitialState 
  426.  
  427.  
  428. //----------------------------------------------------------------------------------------
  429. // TCalcDocument::DoMakeViews: 
  430. //----------------------------------------------------------------------------------------
  431. #pragma segment AOpen
  432.  
  433. void TCalcDocument::DoMakeViews(Boolean forPrinting)
  434. {
  435.     TCalcWindow * aCalcWindow;
  436.     TEntryView * aTEntryView;
  437.     TCellsView * aCellsView;
  438.     TColumnsView * aColumnsView;
  439.     TRowsView * aRowsView;
  440.     TCoordView * aCoordView;
  441.     TSecondaryScroller * aRowScroller;
  442.     TSecondaryScroller * aColumnScroller;
  443.     TPrimaryScroller * aCalcScroller;
  444.     TCalcPrintHandler * aPrintHandler;
  445.     VPoint aVPt;
  446.  
  447.     aCalcWindow = (TCalcWindow *)(gViewServer->NewTemplateWindow(kCalcWindowType, this));
  448.     FailNIL(aCalcWindow);                        // We still must do FailNIL after NewTemplateWindow calls!!!
  449.  
  450.     aCellsView = (TCellsView *)(aCalcWindow->FindSubView('CELL'));
  451.     aRowsView = (TRowsView *)(aCalcWindow->FindSubView('ROWS'));
  452.     aColumnsView = (TColumnsView *)(aCalcWindow->FindSubView('COLS'));
  453.     aTEntryView = (TEntryView *)(aCalcWindow->FindSubView('ENTV'));
  454.     aCoordView = (TCoordView *)(aCalcWindow->FindSubView('CORD'));
  455.  
  456.  
  457.     fCellsView = aCellsView;
  458.     fRowsView = aRowsView;
  459.     fColumnsView = aColumnsView;
  460.     fEntryView = aTEntryView;
  461.     fCoordView = aCoordView;
  462.  
  463.     // The TSectionBehavior is now added to the TCellsView in the 'View' resource (see Calc.r).
  464.     // this->DoAddSectionBehavior(fCellsView);        // add support for Ed Mgr shortcuts
  465.  
  466.     if (!forPrinting)
  467.     {
  468.         aTEntryView->fText = NULL;
  469.         aTEntryView->fText = NewPermHandle(0);
  470.         aTEntryView->StuffText(aTEntryView->fText);// Stuff the initial text in 
  471.     }
  472.  
  473.     // The entry view is the target. Its next handler is the cells view
  474.     // TEntryView.DoPostCreate sets the fControlChars field so that Return, Enter etc. 
  475.     // are passed on to the cells view
  476.  
  477.     aCalcWindow->SetWindowTarget(aTEntryView);
  478.     aTEntryView->fNextHandler = aCellsView;
  479.  
  480.     // set up the cells view scroller to scroll the rows and columns too 
  481.     aCalcScroller = (TPrimaryScroller *)(aCellsView->GetScroller(TRUE));
  482.     SetVPt(aVPt, kCellWidth, kCellHeight);
  483.     aCalcScroller->SetScrollParameters(aVPt, TRUE, TRUE);
  484.  
  485.     aColumnScroller = (TSecondaryScroller *)(aColumnsView->GetScroller(TRUE));
  486.     SetVPt(aVPt, kCellWidth, 0);
  487.     aColumnScroller->SetScrollParameters(aVPt, TRUE, TRUE);
  488.  
  489.     aRowScroller = (TSecondaryScroller *)(aRowsView->GetScroller(TRUE));
  490.     SetVPt(aVPt, 0, kCellHeight);
  491.     aRowScroller->SetScrollParameters(aVPt, TRUE, TRUE);
  492.  
  493.     aCalcScroller->AddSecondaryScroller(aRowScroller, kNotHDependent, kVDependent);
  494.     aCalcScroller->AddSecondaryScroller(aColumnScroller, kHDependent, kNotVDependent);
  495.  
  496.     aPrintHandler = new TCalcPrintHandler;
  497.     aPrintHandler->IStdPrintHandler(this,            // its document 
  498.                                     aCellsView,        // its view 
  499.                                     !kFixedSize,    // horizontal page size is variable 
  500.                                     kFixedSize);    // vertical page size is fixed 
  501.     aPrintHandler->fMinimalMargins = FALSE;
  502.  
  503.  
  504.     // get existing document's column widths 
  505.     CCalcColumnIterator iter(this);
  506.  
  507.     for (TColumn * aColumn = iter.FirstColumn(); iter.More(); aColumn = iter.NextColumn())
  508.  
  509.         if (aColumn->fWidth != kCellWidth)
  510.         {
  511.             fCellsView->SetColWidth(aColumn->fNumber, 1, aColumn->fWidth);
  512.             fColumnsView->SetColWidth(aColumn->fNumber, 1, aColumn->fWidth);
  513.         }
  514.  
  515.     if (forPrinting)                            // Finder printing 
  516.     {
  517.         aPrintHandler->RedoPageBreaks();
  518.     }
  519.     else
  520.     {
  521.         this->ShowReverted();                    // display the views 
  522.  
  523.         fEditRow = 1;                            // default cell to edit is A1 
  524.         fEditColumn = 1;
  525.         this->SetEntry(fEditRow, fEditColumn);
  526.         fSelectionType = kCellSelection;
  527.     }
  528. } // TCalcDocument::DoMakeViews 
  529.  
  530.  
  531. //----------------------------------------------------------------------------------------
  532. // TCalcDocument::Free: 
  533. //----------------------------------------------------------------------------------------
  534. #pragma segment AClose
  535.  
  536. TCalcDocument::~TCalcDocument()
  537. {
  538.     this->FreeData();
  539.  
  540.     fCells = (TCellList *)(FreeListIfObject(fCells));
  541.     fRows = (TRowList *)(FreeListIfObject(fRows));
  542.     fColumns = (TColumnList *)(FreeListIfObject(fColumns));
  543.     fDependencies = (TStandardDependencySpace*) FreeIfObject(fDependencies);
  544. } // TCalcDocument::Free 
  545.  
  546.  
  547. //----------------------------------------------------------------------------------------
  548. // TCalcDocument::DoToPublisher: 
  549. //----------------------------------------------------------------------------------------
  550. #pragma segment ADoCommand
  551.  
  552. void TCalcDocument::DoToPublisher(TCell* theCell,
  553.                                   TPublisher* aPublisher)
  554. {
  555.     GridCell aCell;
  556.  
  557.  
  558.     aCell.v = theCell->fRow;
  559.     aCell.h = theCell->fColumn;
  560.     if (PtInRgn(aCell, ((TRegionDesignator *)(aPublisher->fDesignator))->fDesignation))
  561.         theCell->AddDependent(aPublisher);
  562. } // TCalcDocument::DoToPublisher 
  563.  
  564.  
  565. //----------------------------------------------------------------------------------------
  566. // TCalcDocument::FreeData: 
  567. //----------------------------------------------------------------------------------------
  568. #pragma segment ARes
  569.  
  570. void TCalcDocument::FreeData()
  571. {
  572.     fCells->FreeAll();
  573.     fRows->FreeAll();
  574.     fColumns->FreeAll();
  575.  
  576. } // TCalcDocument::FreeData 
  577.  
  578.  
  579. //----------------------------------------------------------------------------------------
  580. // TCalcDocument::DoNeedDiskSpace: 
  581. //----------------------------------------------------------------------------------------
  582. #pragma segment AWriteFile
  583.  
  584. void TCalcDocument::DoNeedDiskSpace(TFile* itsFile,
  585.                                     long& dataForkBytes,
  586.                                     long& rsrcForkBytes)    // Override
  587. {
  588.     // get Print record requirements 
  589.     Inherited::DoNeedDiskSpace(itsFile, dataForkBytes, rsrcForkBytes);
  590.  
  591.     dataForkBytes += sizeof(CalcDocDiskInfo) + sizeof(RowDiskInfo) * fAllocatedRows + sizeof(ColumnDiskInfo) * fAllocatedColumns;
  592.  
  593.     CCalcCellIterator iter(this);
  594.     for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  595.         dataForkBytes += aCell->GetDiskSize(FALSE);
  596.  
  597. } // TCalcDocument::DoNeedDiskSpace 
  598.  
  599.  
  600. //----------------------------------------------------------------------------------------
  601. // TCalcDocument::DoRead: 
  602. //----------------------------------------------------------------------------------------
  603. #pragma segment AReadFile
  604.  
  605. void TCalcDocument::DoRead(TFile* aFile, Boolean forPrinting)    // override 
  606. {
  607.     short noOfCells;
  608.     short noOfRows;
  609.     short noOfColumns;
  610.     TCell * aCell;
  611.     TRow * aRow;
  612.     TColumn * aColumn;
  613.     long count;
  614.  
  615.     MAVolatile(short, i);
  616.     
  617.     //MAVolatile(RowNumber, r);
  618.     //MAVolatile(ColumnNumber, c);
  619.     
  620.     RowNumber r = 0;    // cannot be volatile because it is passed by reference
  621.     ColumnNumber c = 0;    // cannot be volatile because it is passed by reference
  622.  
  623.     FailInfo fi;
  624.  
  625.     Try(fi)
  626.     {
  627.         Inherited::DoRead(aFile, forPrinting);
  628.         // Get info about the document
  629.         {
  630.             CalcDocDiskInfo theDocInfo;
  631.  
  632.  
  633.             count = sizeof(CalcDocDiskInfo);
  634.             FailOSErr(aFile->ReadData(&theDocInfo, count));
  635.  
  636.             fDimensions = theDocInfo.dimensions;
  637.             fCalcMode = theDocInfo.calcMode;
  638.             noOfRows = theDocInfo.allocatedRows;
  639.             noOfColumns = theDocInfo.allocatedColumns;
  640.             fAllocatedCells = theDocInfo.allocatedCells;
  641.             fSelectionType = kNoSelection;
  642.             fEditRow = theDocInfo.editRow;
  643.             fEditColumn = theDocInfo.editColumn;
  644.  
  645.             fNoOfRows = fDimensions.bottom - fDimensions.top + 1;
  646.             fNoOfColumns = fDimensions.right - fDimensions.left + 1;
  647.  
  648.             // Save the number of cells to be read, then set fAllocatedCells to
  649.             // zero.  As each cell is read fAllocatedCells is incremented.
  650.             // When we've finished, noOfCells must equal fAllocatedCells. 
  651.             noOfCells = fAllocatedCells;
  652.             this->DoInitialState();                // clear allocation counts 
  653.         }
  654.  
  655.         r = 0;
  656.         c = 0;
  657.         i = 0;                                    // Initialized so failure handler knows
  658.                                                 // where we died
  659.  
  660.         for (i = 1; i <= noOfRows; i++)            // Get info about each row 
  661.         {
  662.             count = sizeof(r);
  663.             FailOSErr(aFile->ReadData(&r, count));
  664.             aRow = this->GetRow(r);
  665.             aRow->ReadFromDisk(aFile);
  666.         }
  667.  
  668.         for (i = 1; i <= noOfColumns; i++)        // Get info about each column 
  669.         {
  670.             count = sizeof(c);
  671.             FailOSErr(aFile->ReadData(&c, count));
  672.             aColumn = this->GetColumn(c);
  673.             aColumn->ReadFromDisk(aFile);
  674.         }
  675.  
  676.         for (i = 1; i <= noOfCells; i++)        // Read in the cells 
  677.         {
  678.             ReadCellCoordinate(aFile, r, c);
  679.             aCell = this->GetCell(r, c);
  680.             aCell->ReadFromDisk(aFile);
  681.         }
  682.  
  683. #if qDebug
  684.         if (gIntenseDebugging)
  685.         {
  686.             fprintf(stderr, "TCalcDocument.DoRead: noOfCells=%d", noOfCells);
  687.             if (noOfCells != fAllocatedCells)
  688.             {
  689.                 fprintf(stderr, "TCalcDocument.DoRead: Wrong number of cells.  noOfCells=%d, fAllocatedCells=%d", noOfCells, fAllocatedCells);
  690.                 ProgramBreak("");
  691.             }
  692.         }
  693. #endif
  694.  
  695.         fi.Success();
  696.     }
  697.     else
  698.     {
  699.         // Oh Boy are we in trouble 
  700.         // Need to set back rows and columns to reflect the number read in so
  701.         // the freedata routine (which will eventually be called by other
  702.         // failure handlers on the stack) won't try to free unallocated objects
  703.  
  704.         if (c == 0)
  705.         {
  706.             // We died while reading the rows in
  707.             fNoOfRows = r - 1;
  708.             fNoOfColumns = 0;
  709.         }
  710.         else if (i == 0)
  711.         {
  712.             // Died in the columns 
  713.             fNoOfColumns = c - 1;
  714.         }
  715.  
  716.         fi.ReSignal();                            // tell everyone else we died too.
  717.     }
  718. } // TCalcDocument::DoRead 
  719.  
  720.  
  721. //----------------------------------------------------------------------------------------
  722. // TCalcDocument::DoWrite: 
  723. //----------------------------------------------------------------------------------------
  724. #pragma segment AWriteFile
  725.  
  726. void TCalcDocument::DoWrite(TFile* aFile, Boolean makingCopy)    // Override
  727. {
  728.     short cellsWritten;
  729.     CRect r;
  730.  
  731.  
  732.     Inherited::DoWrite(aFile, makingCopy);
  733.  
  734.     if (aFile != NULL)
  735.     {
  736.         // Write info about the document 
  737.         {
  738.             CalcDocDiskInfo theDocInfo;
  739.             long count;
  740.  
  741.             theDocInfo.dimensions = fDimensions;
  742.             theDocInfo.calcMode = fCalcMode;
  743.             theDocInfo.allocatedRows = fAllocatedRows;
  744.             theDocInfo.allocatedColumns = fAllocatedColumns;
  745.             theDocInfo.allocatedCells = fAllocatedCells;
  746.             theDocInfo.selectionType = kNoSelection;
  747.             theDocInfo.editRow = fEditRow;
  748.             theDocInfo.editColumn = fEditColumn;
  749.             count = sizeof(CalcDocDiskInfo);
  750.             FailOSErr(aFile->WriteData(&theDocInfo, count));
  751.         }
  752.  
  753.         {
  754.             // Write info about each row 
  755.             CCalcRowIterator iter(this);
  756.             for (TRow * aRow = iter.FirstRow(); iter.More(); aRow = iter.NextRow())
  757.                 aRow->WriteToDisk(aFile);        // EachExistingRowDo(WriteRow);
  758.         }
  759.  
  760.         {
  761.             // Write info about each column 
  762.             CCalcColumnIterator iter(this);
  763.             for (TColumn * aColumn = iter.FirstColumn(); iter.More(); aColumn = iter.NextColumn())
  764.             // aColumn->fWidth = fColumnsView->GetColWidth(aCell.h); 
  765.                 aColumn->WriteToDisk(aFile);
  766.             // this was "EachExistingColumnDo(WriteColumn);    "
  767.         }
  768.  
  769.         cellsWritten = 0;
  770.         {
  771.             // Write out the cells
  772.             CExistingCalcCellIterator iter(this);
  773.             for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  774.             {
  775.                 aCell->WriteToDisk(aFile);
  776.                 cellsWritten = cellsWritten + 1;
  777.             }
  778.             // EachExistingCellDo(WriteCell);             
  779.         }
  780.  
  781. #if qDebug
  782.         if (cellsWritten != fAllocatedCells)
  783.             ProgramBreak("DoWrite: Incorrect number of cells written");
  784. #endif
  785.  
  786.     }
  787. } // TCalcDocument::DoWrite 
  788.  
  789.  
  790. //----------------------------------------------------------------------------------------
  791. // TCalcDocument::DoSetupMenus: 
  792. //----------------------------------------------------------------------------------------
  793. #pragma segment ARes
  794.  
  795. void TCalcDocument::DoSetupMenus()    // override 
  796.  
  797. {
  798.     Inherited::DoSetupMenus();
  799.  
  800.     Enable(cRecalculate, TRUE);
  801.     EnableCheck(cAutoCalc, TRUE, IsAutoCalc());
  802.     EnableCheck(cManualCalc, TRUE, fCalcMode == kManual);
  803.  
  804.     if (fColumnIsSelected)
  805.     {
  806.         FormatRecord columnFormat = ColumnExists(fEditColumn) ?
  807.                                     GetColumn(fEditColumn)->fFormat : gDefaultFormat;
  808.  
  809.         short justification = columnFormat.fJustification;
  810.         EnableCheck(cSystemJustify, TRUE, justification == teFlushDefault);
  811.         EnableCheck(cForceLeftJustify, TRUE, justification == teFlushLeft);
  812.         EnableCheck(cRightJustify, TRUE, justification == teFlushRight);
  813.         EnableCheck(cCenter, TRUE, justification == teCenter);
  814.  
  815.         TypeOfStyle theStyle = columnFormat.fStyle;
  816.         EnableCheck(cGeneral, TRUE, theStyle == kGeneral);
  817.         EnableCheck(cDecimal, TRUE, theStyle == kDecimalStyle);
  818.         EnableCheck(cNoDecimal, TRUE, theStyle == kNoDecimal);
  819.         EnableCheck(cScientific, TRUE, theStyle == kScientific);
  820.     }
  821.     else
  822.     {
  823.         Enable(cSystemJustify, FALSE);
  824.         Enable(cForceLeftJustify, FALSE);
  825.         Enable(cRightJustify, FALSE);
  826.         Enable(cCenter, FALSE);
  827.  
  828.         Enable(cGeneral, FALSE);
  829.         Enable(cDecimal, FALSE);
  830.         Enable(cNoDecimal, FALSE);
  831.         Enable(cScientific, FALSE);
  832.     }
  833.  
  834. } // TCalcDocument::DoSetupMenus 
  835.  
  836.  
  837. //----------------------------------------------------------------------------------------
  838. // TCalcDocument::DoMenuCommand: 
  839. //----------------------------------------------------------------------------------------
  840. #pragma segment ASelCommand
  841.  
  842. void TCalcDocument::DoMenuCommand(CommandNumber aCommandNumber)    // Override
  843. {
  844.     switch (aCommandNumber)
  845.     {
  846.         case cRecalculate:
  847.             {
  848.                 DoRecalculate(kForceAutomatic, kUpdateDependencies);
  849.                 break;
  850.             }
  851.         case cAutoCalc:
  852.             {
  853.                 fCalcMode = kAutomatic;
  854.                 DoRecalculate(kForceAutomatic, kUpdateDependencies);
  855.                 break;
  856.             }
  857.         case cManualCalc:
  858.             {
  859.                 fCalcMode = kManual;
  860.                 break;
  861.             }
  862.  
  863.         case cGeneral:
  864.         case cNoDecimal:
  865.         case cDecimal:
  866.         case cScientific:
  867.         case cSystemJustify:
  868.         case cForceLeftJustify:
  869.         case cRightJustify:
  870.         case cCenter:
  871.             {
  872.                 TColumnFormatter* aColumnFormatter = new TColumnFormatter;
  873.                 aColumnFormatter->IFormatter(this, aCommandNumber);
  874.                 PostCommand(aColumnFormatter);
  875.                 break;
  876.             }
  877.  
  878.         default:
  879.             {
  880.                 Inherited::DoMenuCommand(aCommandNumber);
  881.                 break;
  882.             }
  883.     }                                            // switch!
  884. } // TCalcDocument::DoMenuCommand 
  885.  
  886.  
  887. //----------------------------------------------------------------------------------------
  888. // TCalcDocument::AddCell: 
  889. //----------------------------------------------------------------------------------------
  890. #pragma segment ADoCommand
  891.  
  892. void TCalcDocument::AddCell(TCell* theCell,
  893.                             RowNumber r,
  894.                             ColumnNumber c)
  895. {
  896.     CRect aRect;
  897.     CSectionIterator iter(this);
  898.  
  899.     theCell->fCalcDocument = this;
  900.     theCell->fRow = r;
  901.     theCell->fColumn = c;
  902.  
  903.     fCells->Insert(theCell);
  904.     fAllocatedCells = fAllocatedCells + 1;
  905.  
  906.     SetRect(aRect, c, r, c, r);
  907.     UnionRect(aRect, fInUseBounds, fInUseBounds);
  908.  
  909.     for (TSection * aSection = iter.FirstSection(); iter.More(); aSection = iter.NextSection())
  910.         if (aSection->GetSectionType() == stPublisher)
  911.             this->DoToPublisher(theCell, (TPublisher *)aSection);
  912. } // TCalcDocument::AddCell 
  913.  
  914.  
  915. //----------------------------------------------------------------------------------------
  916. // TCalcDocument::CellExists: 
  917. //----------------------------------------------------------------------------------------
  918. #pragma segment ARes
  919.  
  920. Boolean TCalcDocument::CellExists(RowNumber r, ColumnNumber c)
  921. {
  922.     TCell * aCell;
  923.  
  924.  
  925.     aCell = fCells->GetCell(r, c);
  926.     return (aCell != NULL) && (!aCell->fDeleted);
  927. } // TCalcDocument::CellExists 
  928.  
  929.  
  930. //----------------------------------------------------------------------------------------
  931. // TCalcDocument::DeleteCell: 
  932. //----------------------------------------------------------------------------------------
  933. #pragma segment ARes
  934.  
  935. void TCalcDocument::DeleteCell(RowNumber r, ColumnNumber c)
  936. {
  937.     TCell * theCell = GetExistingCell(r, c);
  938.     if (theCell)
  939.     {
  940.         theCell->SetDeleteState(TRUE);
  941.         fAllocatedCells = fAllocatedCells - 1;
  942.         if (theCell == fEditCell)
  943.             fEntryView->SetToString(gEmptyString);
  944.     }
  945. } // TCalcDocument::DeleteCell 
  946.  
  947.  
  948. //----------------------------------------------------------------------------------------
  949. // TCalcDocument::IsExistingCell: 
  950. //----------------------------------------------------------------------------------------
  951. #pragma segment ARes
  952.  
  953. Boolean TCalcDocument::IsExistingCell(TCell* aCell)
  954.  
  955. {
  956.     // returns true if its an ALLOCATED cell 
  957.     return (!aCell->fDeleted);
  958. } // TCalcDocument::IsExistingCell 
  959.  
  960.  
  961. //----------------------------------------------------------------------------------------
  962. // TCalcDocument::EditCell: Change the formula of the cell being edited to the CString in
  963. // the entry view
  964. //----------------------------------------------------------------------------------------
  965. #pragma segment ADoCommand
  966.  
  967. void TCalcDocument::EditCell()
  968. {
  969.     CStr255 theString;
  970.  
  971.  
  972.     fEntryView->GetAsString(theString);
  973.     if (fEditCell == NULL)
  974.         fEditCell = GetCell(fEditRow, fEditColumn);
  975.     fEditCell->SetToString(theString);
  976. } // TCalcDocument::EditCell 
  977.  
  978.  
  979. //----------------------------------------------------------------------------------------
  980. // TCalcDocument::FreeCell: 
  981. //----------------------------------------------------------------------------------------
  982. #pragma segment ARes
  983.  
  984. void TCalcDocument::FreeCell(TCell* theCell)
  985. {
  986. #if qDebug
  987.     if (fCells->GetCell(theCell->fRow, theCell->fColumn) != theCell)
  988.         ProgramBreak("TCalcDocument.FreeCell: Cell table inconsistent");
  989. #endif
  990.  
  991.     fCells->Delete(theCell);
  992.  
  993.     theCell = (TCell *)(FreeIfObject(theCell));
  994. } // TCalcDocument::FreeCell 
  995.  
  996.  
  997. //----------------------------------------------------------------------------------------
  998. // TCalcDocument::FreeDeletedCells: 
  999. //----------------------------------------------------------------------------------------
  1000. #pragma segment ADoCommand
  1001.  
  1002. void TCalcDocument::FreeDeletedCells()
  1003. {
  1004.     CCalcCellIterator iter(this);
  1005.     for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  1006.         if (aCell->fDeleted)
  1007.             this->FreeCell(aCell);
  1008. } // TCalcDocument::FreeDeletedCells 
  1009.  
  1010.  
  1011. //----------------------------------------------------------------------------------------
  1012. // TCalcDocument::GetCell: Return the cell object for the given coordinates. If a cell
  1013. // object doesn't already exist, create one.
  1014. //----------------------------------------------------------------------------------------
  1015. #pragma segment ARes
  1016.  
  1017. TCell* TCalcDocument::GetCell(RowNumber r, ColumnNumber c)
  1018. {
  1019.     TCell * theCell;
  1020.  
  1021.  
  1022.     theCell = fCells->GetCell(r, c);
  1023.     if (theCell == NULL)
  1024.     {
  1025.         theCell = new TCell;
  1026.         theCell->ICell(this, r, c);
  1027.         this->AddCell(theCell, r, c);
  1028.     }
  1029.  
  1030.     return theCell;
  1031. } // TCalcDocument::GetCell 
  1032.  
  1033.  
  1034. //----------------------------------------------------------------------------------------
  1035. // TCalcDocument::GetExistingCell: 
  1036. //----------------------------------------------------------------------------------------
  1037. #pragma segment ARes
  1038.  
  1039. TCell* TCalcDocument::GetExistingCell(RowNumber r, ColumnNumber c)
  1040. {
  1041.     return fCells->GetCell(r, c);
  1042. } // TCalcDocument::GetExistingCell 
  1043.  
  1044.  
  1045. //----------------------------------------------------------------------------------------
  1046. // TCalcDocument::IsAutoCalc: 
  1047. //----------------------------------------------------------------------------------------
  1048. #pragma segment ARes
  1049.  
  1050. Boolean TCalcDocument::IsAutoCalc()
  1051. {
  1052.     return fCalcMode == kAutomatic;
  1053. } // TCalcDocument::IsAutoCalc 
  1054.  
  1055.  
  1056. //----------------------------------------------------------------------------------------
  1057. // TCalcDocument::SetEntry:  Set the CString in TEntryView to the formula in the cell 
  1058. //----------------------------------------------------------------------------------------
  1059. #pragma segment ADoCommand
  1060.  
  1061. void TCalcDocument::SetEntry(RowNumber r, ColumnNumber c)
  1062. {
  1063.     TCell * theCell = this->GetExistingCell(r, c);
  1064.  
  1065.     if (theCell && !theCell->fDeleted)
  1066.     {
  1067.         CStr255 theString;
  1068.         theCell->GetAsString(theString);
  1069.         fEntryView->SetToString(theString);
  1070.     }
  1071.     else
  1072.         fEntryView->SetToString(gEmptyString);
  1073. } // TCalcDocument::SetEntry 
  1074.  
  1075.  
  1076. //----------------------------------------------------------------------------------------
  1077. // TCalcDocument::UndeleteCell: 
  1078. //----------------------------------------------------------------------------------------
  1079. #pragma segment ARes
  1080.  
  1081. void TCalcDocument::UndeleteCell(RowNumber r, ColumnNumber c)
  1082. {
  1083.     TCell * theCell;
  1084.  
  1085.     theCell = this->GetExistingCell(r, c);
  1086.     if (theCell != NULL)
  1087.     {
  1088.         theCell->SetDeleteState(FALSE);
  1089.         fAllocatedCells = fAllocatedCells + 1;
  1090.     }
  1091. } // TCalcDocument::UndeleteCell 
  1092.  
  1093.  
  1094. //----------------------------------------------------------------------------------------
  1095. // TCalcDocument::AddRow: 
  1096. //----------------------------------------------------------------------------------------
  1097. #pragma segment ADoCommand
  1098.  
  1099. void TCalcDocument::AddRow(TRow* theRow)
  1100. {
  1101.     fRows->Insert(theRow);
  1102.     fAllocatedRows = fAllocatedRows + 1;
  1103.  
  1104.     fInUseBounds.top = Min(fInUseBounds.top, theRow->fNumber);
  1105.     fInUseBounds.bottom = Max(fInUseBounds.bottom, theRow->fNumber);
  1106. } // TCalcDocument::AddRow 
  1107.  
  1108.  
  1109. //----------------------------------------------------------------------------------------
  1110. // TCalcDocument::GetRow: 
  1111. //----------------------------------------------------------------------------------------
  1112. #pragma segment ARes
  1113.  
  1114. TRow* TCalcDocument::GetRow(RowNumber r)
  1115. {
  1116.     TRow * theRow;
  1117.  
  1118.     theRow = fRows->GetRow(r);
  1119.     if (theRow == NULL)
  1120.     {
  1121.         theRow = new TRow();
  1122.         theRow->IRow(r);
  1123.         this->AddRow(theRow);
  1124.     }
  1125.  
  1126.     return theRow;
  1127. } // TCalcDocument::GetRow 
  1128.  
  1129.  
  1130. //----------------------------------------------------------------------------------------
  1131. // TCalcDocument::RowExists: 
  1132. //----------------------------------------------------------------------------------------
  1133. #pragma segment ADoCommand
  1134.  
  1135. Boolean TCalcDocument::RowExists(RowNumber r)
  1136. {
  1137.     return fRows->GetRow(r) != NULL;
  1138. } // TCalcDocument::RowExists 
  1139.  
  1140.  
  1141. //----------------------------------------------------------------------------------------
  1142. // TCalcDocument::AddColumn: 
  1143. //----------------------------------------------------------------------------------------
  1144. #pragma segment ADoCommand
  1145.  
  1146. void TCalcDocument::AddColumn(TColumn* theColumn)
  1147. {
  1148.     fColumns->Insert(theColumn);
  1149.     fAllocatedColumns = fAllocatedColumns + 1;
  1150.  
  1151.     fInUseBounds.left = Min(fInUseBounds.left, theColumn->fNumber);
  1152.     fInUseBounds.right = Max(fInUseBounds.right, theColumn->fNumber);
  1153. } // TCalcDocument::AddColumn 
  1154.  
  1155.  
  1156. //----------------------------------------------------------------------------------------
  1157. // TCalcDocument::ColumnExists: 
  1158. //----------------------------------------------------------------------------------------
  1159. #pragma segment ADoCommand
  1160.  
  1161. Boolean TCalcDocument::ColumnExists(ColumnNumber c)
  1162. {
  1163.     return (fColumns->GetColumn(c) != NULL);
  1164. } // TCalcDocument::ColumnExists 
  1165.  
  1166.  
  1167. //----------------------------------------------------------------------------------------
  1168. // TCalcDocument::GetColumn: 
  1169. //----------------------------------------------------------------------------------------
  1170. #pragma segment ARes
  1171.  
  1172. TColumn* TCalcDocument::GetColumn(ColumnNumber c)
  1173. {
  1174.     TColumn * theColumn;
  1175.  
  1176.     theColumn = fColumns->GetColumn(c);
  1177.  
  1178.     if (theColumn == NULL)
  1179.     {
  1180.         theColumn = new TColumn;
  1181.         theColumn->IColumn(c);
  1182.         this->AddColumn(theColumn);
  1183.     }
  1184.  
  1185.     return theColumn;
  1186. } // TCalcDocument::GetColumn 
  1187.  
  1188.  
  1189. //----------------------------------------------------------------------------------------
  1190. // TCalcDocument::CellInRange: 
  1191. //----------------------------------------------------------------------------------------
  1192. #pragma segment ADoCommand
  1193.  
  1194. Boolean TCalcDocument::CellInRange(short r,
  1195.                                    short c,
  1196.                                    CRect& range)
  1197. {
  1198.     return (r >= range.top) && (r <= range.bottom) && (c >= range.left) && (c <= range.right);
  1199. } // TCalcDocument::CellInRange 
  1200.  
  1201.  
  1202. //----------------------------------------------------------------------------------------
  1203. // TCalcDocument::ConstrainToUsedCells: Given a range of cells, this returns the range of
  1204. // cells that fall within the range of used cells. This is used to optimize performance so
  1205. // that we don't try to operate on cells that we know have never been used (i.e.
  1206. // allocated).
  1207. //----------------------------------------------------------------------------------------
  1208. #pragma segment ADoCommand
  1209.  
  1210. void TCalcDocument::ConstrainToUsedCells(CRect& cellRange)
  1211. {
  1212.     cellRange.top = Max(cellRange.top, fInUseBounds.top);
  1213.     cellRange.left = Max(cellRange.left, fInUseBounds.left);
  1214.     cellRange.bottom = Min(cellRange.bottom, fInUseBounds.bottom);
  1215.     cellRange.right = Min(cellRange.right, fInUseBounds.right);
  1216. } // TCalcDocument::ConstrainToUsedCells 
  1217.  
  1218.  
  1219. //----------------------------------------------------------------------------------------
  1220. // TCalcDocument::DoRecalculate: 
  1221. //----------------------------------------------------------------------------------------
  1222. #pragma segment ADoCommand
  1223.  
  1224. void TCalcDocument::DoRecalculate(Boolean forceAutomatic,
  1225.                                   Boolean setDependents)
  1226. {
  1227.     if (IsAutoCalc() || forceAutomatic)
  1228.     {
  1229.         CCalcCellIterator iter(this);
  1230.         for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  1231.             aCell->Recalculate(forceAutomatic, setDependents);
  1232.     }
  1233.     else
  1234.     {
  1235.         CSelectedExistingCalcCellIterator iter(this);
  1236.         for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  1237.             aCell->Recalculate(forceAutomatic, setDependents);
  1238.     }
  1239.     this->SetChangeCount(Max(fChangeCount + 1, 1));// enable Save - document may have changed 
  1240. } // TCalcDocument::DoRecalculate 
  1241.  
  1242.  
  1243. //----------------------------------------------------------------------------------------
  1244. // TCalcDocument::SetUserSelection: 
  1245. //----------------------------------------------------------------------------------------
  1246. #pragma segment MAViewRes
  1247.  
  1248. void TCalcDocument::SetUserSelection(TDesignator* newSelection)
  1249. {
  1250.     Inherited::SetUserSelection(newSelection);
  1251.     
  1252.     if (fCellsView && fCellsView->fSelections)
  1253.     {
  1254.         TDesignator * userSelection = this->GetUserSelection();
  1255.         if ((userSelection) && userSelection->DescendsFrom(TRegionDesignator::GetClassDescStatic()))
  1256.             fCellsView->SetSelection(((TRegionDesignator *)(userSelection))->fDesignation, kDontExtend, kHighlight, kSelect);
  1257.         //fCellsView->ForceRedraw();
  1258.     }
  1259. } // TCalcDocument::SetUserSelection 
  1260.  
  1261. //----------------------------------------------------------------------------------------
  1262. // TCalcDocument::UserSelectionChanged: 
  1263. //----------------------------------------------------------------------------------------
  1264. #pragma segment ARes
  1265.  
  1266. void TCalcDocument::UserSelectionChanged(TView* changedView)// override 
  1267. {
  1268.     // let the document's selection designator know that the designation has changed 
  1269.     TDesignator * userSelection = this->GetUserSelection();
  1270.     if ((userSelection != NULL) && userSelection->DescendsFrom(TRegionDesignator::GetClassDescStatic()))
  1271.         CopyRgn(fCellsView->fSelections, ((TRegionDesignator *)(userSelection))->fDesignation);
  1272.  
  1273.     Inherited::UserSelectionChanged(changedView);
  1274. } // TCalcDocument::UserSelectionChanged 
  1275.  
  1276.  
  1277. //----------------------------------------------------------------------------------------
  1278. // TCalcDocument::DoWriteData: 
  1279. //----------------------------------------------------------------------------------------
  1280. #pragma segment ANonRes
  1281.  
  1282. void TCalcDocument::DoWriteData(const OSType aScrapType,
  1283.                                 TDesignator* aDesignator,
  1284.                                 TStream* aStream)// override 
  1285. {
  1286.     if (aScrapType == 'TEXT')
  1287.     {
  1288.         Handle textHandle = fCellsView->DesignatorAsTEXT(aDesignator);
  1289.         SignedByte savedState = LockHandleHigh(textHandle);
  1290.  
  1291.         aStream->WriteBytes((*textHandle), GetHandleSize(textHandle));
  1292.  
  1293.         HSetState(textHandle, savedState);
  1294.         DisposeHandle(textHandle);
  1295.     }
  1296.     else if (aScrapType == fScrapType)
  1297.         this->DoWritePrivateTypes(aDesignator, aStream);
  1298. } // TCalcDocument::DoWriteData 
  1299.  
  1300.  
  1301. //----------------------------------------------------------------------------------------
  1302. // TCalcDocument::DoWritePrivateTypes: 
  1303. //----------------------------------------------------------------------------------------
  1304. #pragma segment ANonRes
  1305.  
  1306. void TCalcDocument::DoWritePrivateTypes(TDesignator* aDesignator,
  1307.                                         TStream* aStream)
  1308. {
  1309.     CRect selection;
  1310.     short i;
  1311.     RowDiskInfo rowInfo;
  1312.     ColumnDiskInfo columnInfo;
  1313.  
  1314.     if (aDesignator->DescendsFrom(TRegionDesignator::GetClassDescStatic()))
  1315.     {
  1316.         // Write out extent. 
  1317.         selection = GetRgnBounds(((TRegionDesignator *)(aDesignator))->fDesignation);
  1318.         aStream->WriteBytes(&selection, sizeof(selection));
  1319.  
  1320.         // Write out row info. 
  1321.         for (i = selection.top; i <= selection.bottom; i++)
  1322.         {
  1323.             rowInfo.number = GetRow(i)->fNumber;// Need a GetRowDiskInfo(). 
  1324.             aStream->WriteBytes(&rowInfo, sizeof(rowInfo));
  1325.         }
  1326.  
  1327.         // Write out column info. 
  1328.         for (i = selection.left; i <= selection.right; i++)
  1329.         {
  1330.             TColumn * aColumn;                    //temporary variable scoped to the for loop only!!!
  1331.  
  1332.             aColumn = this->GetColumn(i);
  1333.             columnInfo.number = aColumn->fNumber;
  1334.             columnInfo.format = aColumn->fFormat;
  1335.             columnInfo.width = aColumn->fWidth;
  1336.             aStream->WriteBytes(&columnInfo, sizeof(columnInfo));
  1337.         }
  1338.  
  1339.         // Write out cell info. 
  1340.         CCellIterator iter(fCellsView, selection[topLeft], selection[botRight], kIterateForward, kIterateForward, CCellIterator::kIterateRowMajor);
  1341.         for (GridCell aGridCell = iter.FirstCell(); iter.More(); aGridCell = iter.NextCell())
  1342.         {
  1343.             CellDiskInfo cellInfo;
  1344.             TCell * aCell;
  1345.  
  1346.             // write out cell info 
  1347.             aCell = this->GetCell(aGridCell.v, aGridCell.h);
  1348.             cellInfo.kind = aCell->fKind;
  1349.             cellInfo.error = aCell->fError;
  1350.             cellInfo.value = aCell->fValue;
  1351.             cellInfo.noOfReferences = 0;
  1352.             cellInfo.formula = aCell->fFormula;
  1353.             aStream->WriteBytes(&cellInfo, sizeof(cellInfo));
  1354.         }
  1355.     }
  1356.     else if (qDebug)
  1357.         ProgramBreak("I don't recognize that designator…sigh!");
  1358. } // TCalcDocument::DoWritePrivateTypes 
  1359.  
  1360.  
  1361. //----------------------------------------------------------------------------------------
  1362. // TCalcDocument::DoReadData: 
  1363. //----------------------------------------------------------------------------------------
  1364. #pragma segment ANonRes
  1365.  
  1366. void TCalcDocument::DoReadData(const OSType aScrapType,
  1367.                                TDesignator* aDesignator,
  1368.                                TStream* aStream,
  1369.                                long length)    // override 
  1370. {
  1371.     if (aScrapType == 'TEXT')
  1372.         this->DoReadTEXT(aDesignator, aStream, length);
  1373.     else if (aScrapType == fScrapType)
  1374.         this->DoReadPrivateTypes(aDesignator, aStream);
  1375. } // TCalcDocument::DoReadData 
  1376.  
  1377.  
  1378. //----------------------------------------------------------------------------------------
  1379. // TCalcDocument::DoReadPrivateTypes: 
  1380. //----------------------------------------------------------------------------------------
  1381. #pragma segment ANonRes
  1382.  
  1383. void TCalcDocument::DoReadPrivateTypes(TDesignator* aDesignator,
  1384.                                        TStream* aStream)
  1385.  
  1386. {
  1387.     CRect subBounds;                            // bounds of the subscriber 
  1388.     CRect pubBounds;                            // bounds of the publisher 
  1389.     short i;
  1390.     RowDiskInfo rowInfo;
  1391.     ColumnDiskInfo columnInfo;
  1392.     CPoint difference;
  1393.  
  1394.     // read in the publisher bounds and figure out the difference 
  1395.     subBounds = GetRgnBounds(((TRegionDesignator *)(aDesignator))->fDesignation);
  1396.     aStream->ReadBytes(&pubBounds, sizeof(pubBounds));
  1397.     difference.h = subBounds.left - pubBounds.left;
  1398.     difference.v = subBounds.top - pubBounds.top;
  1399.  
  1400.     // Read in row info. 
  1401.     for (i = pubBounds.top; i <= pubBounds.bottom; i++)
  1402.         aStream->ReadBytes(&rowInfo, sizeof(rowInfo));
  1403.  
  1404.     // Read in the col info and set it. 
  1405.     for (i = pubBounds.left; i <= pubBounds.right; i++)
  1406.     {
  1407.         aStream->ReadBytes(&columnInfo, sizeof(columnInfo));
  1408.         if ((i + difference.h >= subBounds.left) && (i + difference.h <= subBounds.right) && (!ColumnExists(i)))
  1409.         {
  1410.             TColumn * aColumn;                    //local variable to do WITH scoped to this "if" only
  1411.  
  1412.             aColumn = this->GetColumn(i);
  1413.             aColumn->fNumber = columnInfo.number;
  1414.             aColumn->fFormat = columnInfo.format;
  1415.             aColumn->fWidth = columnInfo.width;
  1416.         }
  1417.     }
  1418.  
  1419.     // Read in the cell info.
  1420.     CCellIterator iter(fCellsView, pubBounds[topLeft], pubBounds[botRight], kIterateForward, kIterateForward, CCellIterator::kIterateRowMajor);
  1421.     for (GridCell aGridCell = iter.FirstCell(); iter.More(); aGridCell = iter.NextCell())
  1422.     {
  1423.         TCell * aCell;
  1424.         CellDiskInfo cellInfo;
  1425.  
  1426.         // map a published cell into subscriber range 
  1427.         aGridCell.v += difference.v;
  1428.         aGridCell.h += difference.h;
  1429.         aCell = this->GetCell(aGridCell.v, aGridCell.h);    // retrieve or create a TCell 
  1430.         aStream->ReadBytes(&cellInfo, sizeof(cellInfo));
  1431.         if ((aGridCell.h >= subBounds.left) && (aGridCell.h <= subBounds.right) && (aGridCell.v >= subBounds.top) && (aGridCell.v <= subBounds.bottom))
  1432.             if ((aCell->fKind != cellInfo.kind) || (aCell->fError != cellInfo.error) || (aCell->fValue != cellInfo.value) || (aCell->fFormula != cellInfo.formula))
  1433.             {
  1434.                 aCell->fFormula = cellInfo.formula;
  1435.                 aCell->Recalculate(TRUE, TRUE);
  1436.                 aCell->invalidate();
  1437.             }
  1438.     }                                            // we're taken care of.
  1439. } // TCalcDocument::DoReadPrivateTypes 
  1440.  
  1441.  
  1442. //----------------------------------------------------------------------------------------
  1443. // TCalcDocument::DoReadTEXT: 
  1444. //----------------------------------------------------------------------------------------
  1445. #pragma segment ANonRes
  1446.  
  1447. void TCalcDocument::DoReadTEXT(TDesignator* aDesignator,
  1448.                                TStream* aStream,
  1449.                                long length)
  1450.  
  1451. {
  1452.     CRect subBounds;                            // bounds of the subscriber 
  1453.     CRect pubBounds;                            // bounds of the publisher 
  1454.     Handle theText;
  1455.  
  1456.  
  1457.     theText = NewPermHandle(length);
  1458.     LockHandleHigh(theText);
  1459.     aStream->ReadBytes((*theText), length);
  1460.     subBounds = GetRgnBounds(((TRegionDesignator *)(aDesignator))->fDesignation);
  1461.     {
  1462.         CCellIterator iter(fCellsView, subBounds[topLeft], subBounds[botRight], kIterateForward, kIterateForward, CCellIterator::kIterateRowMajor);
  1463.         CParseSubscribedText theParser(aDesignator, aStream, length, subBounds, pubBounds);
  1464.         for (GridCell aGridCell = iter.FirstCell(); iter.More(); aGridCell = iter.NextCell())
  1465.         {
  1466.             CStr255 aStr;
  1467.             TCell * aCell;
  1468.  
  1469.             aStr = theParser.ParseSubscribedText(theText, aGridCell);
  1470.             aCell = this->GetCell(aGridCell.v, aGridCell.h);// retrieve or create a TCell 
  1471.             aCell->SetToString(aStr);
  1472.         }
  1473.     }
  1474.     DisposeHandle(theText);
  1475. } // TCalcDocument::DoReadTEXT 
  1476.  
  1477.  
  1478. //----------------------------------------------------------------------------------------
  1479. // TCalcDocument::AddPublisherDependency: 
  1480. //----------------------------------------------------------------------------------------
  1481. #pragma segment ASelCommand
  1482.  
  1483. void TCalcDocument::AddPublisherDependency(TSection* aSection)
  1484. {
  1485.     if (fCellsView && (aSection->GetSectionType() == stPublisher))
  1486.     {
  1487.         // make each publisher a dependent of each cell in the designation 
  1488.         
  1489.         CCellInRegionIterator iter(fCellsView, ((TRegionDesignator *)(aSection->fDesignator))->fDesignation);
  1490.         for (GridCell aGridCell = iter.FirstCell(); iter.More(); aGridCell = iter.NextCell())
  1491.         {
  1492.             if (this->CellExists(aGridCell.v, aGridCell.h))
  1493.             {
  1494.                 TCell * aCell = this->GetCell(aGridCell.v, aGridCell.h);
  1495.                 aCell->AddDependent(aSection);
  1496.             }
  1497.         }
  1498.     }
  1499. } // TCalcDocument::AddPublisherDependency 
  1500.  
  1501.  
  1502. //----------------------------------------------------------------------------------------
  1503. // TCalcDocument::AddSectionAndBorder: 
  1504. //----------------------------------------------------------------------------------------
  1505. #pragma segment ASelCommand
  1506.  
  1507. void TCalcDocument::AddSectionAndBorder(TSection* aSection)
  1508. {
  1509.     Inherited::AddSectionAndBorder(aSection);
  1510.  
  1511.     this->AddPublisherDependency(aSection);
  1512. } // TCalcDocument::AddSectionAndBorder 
  1513.  
  1514.  
  1515. //----------------------------------------------------------------------------------------
  1516. // TCalcDocument::DoPostMakeViews: 
  1517. //----------------------------------------------------------------------------------------
  1518. #pragma segment AOpen
  1519.  
  1520. void TCalcDocument::DoPostMakeViews(Boolean forPrinting)
  1521. {
  1522.     if (!forPrinting)
  1523.     {
  1524.         CSectionIterator iter(this);
  1525.  
  1526.         for (TSection * aSection = iter.FirstSection(); iter.More(); aSection = iter.NextSection())
  1527.             this->AddPublisherDependency(aSection);
  1528.     }
  1529.  
  1530.     Inherited::DoPostMakeViews(forPrinting);
  1531. } // TCalcDocument::DoPostMakeViews 
  1532.  
  1533.  
  1534. //----------------------------------------------------------------------------------------
  1535. // TCalcDocument::DoAddBorder: 
  1536. //----------------------------------------------------------------------------------------
  1537. #pragma segment ASelCommand
  1538.  
  1539. void TCalcDocument::DoAddBorder(TSection* aSection)
  1540. {
  1541.     // adding a section, give it a section adorner 
  1542.     if (fCellsView)
  1543.     {
  1544.         if (aSection->GetSectionType() == stSubscriber)
  1545.             fCellsView->CreateSubscriberAdorner((TSubscriber *)aSection);
  1546.         else
  1547.             fCellsView->CreatePublisherAdorner((TPublisher *)aSection);
  1548.  
  1549.         // invalidate the borders of publishers/subscribers, if we aren't showing all borders
  1550.         if (!fShowSectionBorders)
  1551.         {
  1552.             CAdornerIterator iter(fCellsView);
  1553.     
  1554.             for (TAdorner * anAdorner = iter.FirstAdorner(); iter.More(); anAdorner = iter.NextAdorner())
  1555.                 if ((anAdorner->fIdentifier == kPublisherAdornerID)
  1556.                     || (anAdorner->fIdentifier == kSubscriberAdornerID))
  1557.                     anAdorner->InvalidateAdorner(fCellsView);
  1558.         }
  1559.     }
  1560. } // TCalcDocument::DoAddBorder 
  1561.  
  1562.  
  1563. //----------------------------------------------------------------------------------------
  1564. // TCalcDocument::DoDeleteBorder: 
  1565. //----------------------------------------------------------------------------------------
  1566. #pragma segment ASelCommand
  1567.  
  1568. void TCalcDocument::DoDeleteBorder(TSection* aSection)
  1569. {
  1570.     // adding a section, give it a section adorner 
  1571.     CAdornerIterator iter(fCellsView);
  1572.  
  1573.     for (TAdorner * anAdorner = iter.FirstAdorner(); iter.More(); anAdorner = iter.NextAdorner())
  1574.         if ((anAdorner->fIdentifier == kPublisherAdornerID)
  1575.                 || (anAdorner->fIdentifier == kSubscriberAdornerID))
  1576.             if (((TSectionAdorner *)anAdorner)->fSection == aSection)
  1577.             {
  1578.                 fCellsView->DeleteAdorner(anAdorner, kInvalidate);
  1579.                 break;
  1580.             }
  1581.  
  1582.     // invalidate the borders of publishers/subscribers, if we aren't showing all borders
  1583.     if (!fShowSectionBorders)
  1584.     {
  1585.         CAdornerIterator iter(fCellsView);
  1586.  
  1587.         for (TAdorner * anAdorner = iter.FirstAdorner(); iter.More(); anAdorner = iter.NextAdorner())
  1588.             if ((anAdorner->fIdentifier == kPublisherAdornerID)
  1589.                 || (anAdorner->fIdentifier == kSubscriberAdornerID))
  1590.                 anAdorner->InvalidateAdorner(fCellsView);
  1591.     }
  1592. } // TCalcDocument::DoDeleteBorder 
  1593.  
  1594.  
  1595. //----------------------------------------------------------------------------------------
  1596. // TCalcDocument::RevealSelection: 
  1597. //----------------------------------------------------------------------------------------
  1598. #pragma segment AOpen
  1599.  
  1600. void TCalcDocument::RevealSelection(TDesignator* aSelection)// override 
  1601. {
  1602.     CRect qdExtent;
  1603.     VRect viewRect;
  1604.  
  1605.     Inherited::RevealSelection(aSelection);        // make window front-most 
  1606.  
  1607.     if (aSelection->DescendsFrom(TRegionDesignator::GetClassDescStatic()))
  1608.     {
  1609.         fCellsView->SetSelection(((TRegionDesignator *)(aSelection))->fDesignation, kDontExtend, kHighlight, kSelect);
  1610.  
  1611.         fCellsView->ScrollSelectionIntoView(kRedraw);
  1612.     }
  1613.     else if (qDebug)
  1614.         ProgramBreak("handed an unknown designator");
  1615. } // TCalcDocument::RevealSelection 
  1616.  
  1617.  
  1618. //========================================================================================
  1619. // CLASS TCalcWindow
  1620. //========================================================================================
  1621. #undef Inherited
  1622. #define Inherited TWindow
  1623.  
  1624. #pragma segment ClassDescRes
  1625. MA_DEFINE_CLASS_M1(TCalcWindow, Inherited);
  1626.  
  1627. //----------------------------------------------------------------------------------------
  1628. // TCalcWindow destructor
  1629. //----------------------------------------------------------------------------------------
  1630. #pragma segment MADestructorRes
  1631.  
  1632. TCalcWindow::~TCalcWindow()
  1633. {
  1634. }
  1635.  
  1636. //----------------------------------------------------------------------------------------
  1637. // TCalcWindow::DoPostCreate: 
  1638. //----------------------------------------------------------------------------------------
  1639. #pragma segment AOpen
  1640.  
  1641. void TCalcWindow::DoPostCreate(TDocument*/* itsDocument */ )    // Override
  1642. {
  1643.     CPoint minSize;
  1644.  
  1645.     minSize.h = 284;
  1646.     minSize.v = 126;
  1647.     this->SetResizeLimits(minSize, fResizeLimits[botRight]);
  1648. } // TCalcWindow::DoPostCreate 
  1649.  
  1650.  
  1651. //----------------------------------------------------------------------------------------
  1652. // TCalcWindow::Draw: 
  1653. //----------------------------------------------------------------------------------------
  1654. #pragma segment ARes
  1655.  
  1656. void TCalcWindow::Draw(const VRect& area)    // override 
  1657. {
  1658.     // draw the extra borders for the rows and columns views 
  1659.     PenNormal();
  1660.  
  1661.     // rows 
  1662.     MoveTo(0, 35);
  1663.     Line(kRowTitleWidth - 1, 0);
  1664.  
  1665.     MoveTo(0, 35 + kCellHeight - 1);
  1666.     Line(kRowTitleWidth - 1, 0);
  1667.  
  1668.     // columns 
  1669.     MoveTo(kRowTitleWidth - 1, 35);
  1670.     Line(0, kCellHeight - 1);
  1671.  
  1672.     Inherited::Draw(area);
  1673. } // TCalcWindow::Draw 
  1674.  
  1675.  
  1676.  
  1677. //========================================================================================
  1678. // CLASS TCellsView
  1679. //========================================================================================
  1680. #undef Inherited
  1681. #define Inherited TTextGridView
  1682.  
  1683. #pragma segment ClassDescRes
  1684. MA_DEFINE_CLASS_M1(TCellsView, Inherited);
  1685.  
  1686. //----------------------------------------------------------------------------------------
  1687. // TCellsView destructor
  1688. //----------------------------------------------------------------------------------------
  1689. #pragma segment MADestructorRes
  1690.  
  1691. TCellsView::~TCellsView()
  1692. {
  1693. }
  1694.  
  1695. //----------------------------------------------------------------------------------------
  1696. // TCellsView::CreatePublisherAdorner: 
  1697. //----------------------------------------------------------------------------------------
  1698. #pragma segment GNonRes2
  1699.  
  1700. void TCellsView::CreatePublisherAdorner(TPublisher* aPublisher)
  1701. {
  1702.     TPublisherAdorner * aPublisherAdorner;
  1703.     RgnHandle itsBorderRegion;
  1704.  
  1705.     itsBorderRegion = MakeNewRgn();
  1706.     this->ComputeBorderRgn(itsBorderRegion, ((TRegionDesignator *)(aPublisher->fDesignator))->fDesignation);
  1707.  
  1708.     aPublisherAdorner = new TPublisherAdorner;
  1709.     aPublisherAdorner->IPublisherAdorner(kPublisherAdornerID, aPublisher, itsBorderRegion);
  1710.  
  1711.     this->AddAdorner(aPublisherAdorner, kAdornAfter, fCalcDocument->IsBorderShown(aPublisher));
  1712. } // TCellsView::CreatePublisherAdorner 
  1713.  
  1714.  
  1715. //----------------------------------------------------------------------------------------
  1716. // TCellsView::CreateSubscriberAdorner: 
  1717. //----------------------------------------------------------------------------------------
  1718. #pragma segment GNonRes2
  1719.  
  1720. void TCellsView::CreateSubscriberAdorner(TSubscriber* aSubscriber)
  1721. {
  1722.     TSubscriberAdorner * aSubscriberAdorner;
  1723.     RgnHandle itsBorderRegion;
  1724.  
  1725.     itsBorderRegion = MakeNewRgn();
  1726.     this->ComputeBorderRgn(itsBorderRegion, ((TRegionDesignator *)(aSubscriber->fDesignator))->fDesignation);
  1727.  
  1728.     aSubscriberAdorner = new TSubscriberAdorner;
  1729.     aSubscriberAdorner->ISubscriberAdorner(kSubscriberAdornerID, aSubscriber, itsBorderRegion);
  1730.  
  1731.     this->AddAdorner(aSubscriberAdorner, kAdornAfter, fCalcDocument->IsBorderShown(aSubscriber));
  1732. } // TCellsView::CreateSubscriberAdorner 
  1733.  
  1734.  
  1735. //----------------------------------------------------------------------------------------
  1736. // TCellsView::ComputeBorderRgn: 
  1737. //----------------------------------------------------------------------------------------
  1738. #pragma segment ARes
  1739.  
  1740. void TCellsView::ComputeBorderRgn(RgnHandle itsBorderRegion,
  1741.                                   RgnHandle itsDesignation)
  1742.  
  1743. {
  1744.     CTemporaryRegion tempRgn;
  1745.  
  1746.     if (this->Focus())
  1747.         this->CellsToPixels(itsDesignation, tempRgn);
  1748.  
  1749.     RectRgn(itsBorderRegion, CRect((*tempRgn)->rgnBBox) + CRect(-5, -5, 4, 4));
  1750.     RectRgn(tempRgn, CRect((*tempRgn)->rgnBBox) + CRect(-2, -2, 1, 1));
  1751.  
  1752.     DiffRgn(itsBorderRegion, tempRgn, itsBorderRegion);
  1753. } // TCellsView::ComputeBorderRgn 
  1754.  
  1755.  
  1756. //----------------------------------------------------------------------------------------
  1757. // TCellsView::ICellsView: 
  1758. //----------------------------------------------------------------------------------------
  1759. #pragma segment AOpen
  1760.  
  1761. void TCellsView::ICellsView(TCalcDocument* itsDocument,
  1762.                             Boolean /*forClipboard*/,
  1763.                             TView* itsParent)
  1764. {
  1765.     this->ITextGridView(itsDocument, itsParent, gZeroVPt, gZeroVPt, sizeVariable, sizeVariable, itsDocument->fNoOfRows, itsDocument->fNoOfColumns, 0, kCellWidth, kAdorn, kAdorn, 0, 0, FALSE, gSystemStyle);
  1766.  
  1767.     fCalcDocument = itsDocument;
  1768.     fLastOptionKey = FALSE;                        // Used for DoSetCursor to the grabber hand 
  1769.  
  1770.     fIdleFreq = Max(GetCaretTime() / 2, (long)1);// So we can trackCursor for the GrabberHand.
  1771.     // With MF 7.0 we could setup a VBL that monitered the modifiers and called Wakeup
  1772.     // with our PID. Even better would be a call that set the event manager so that an
  1773.     // event could be returned on modifier key changes… oh, well. 
  1774.  
  1775.     fHelpID = kCellsViewHelp;
  1776.     fHelpIndex = 1;
  1777. } // TCellsView::ICellsView 
  1778.  
  1779.  
  1780. //----------------------------------------------------------------------------------------
  1781. // TCellsView::DoPostCreate: 
  1782. //----------------------------------------------------------------------------------------
  1783. #pragma segment AOpen
  1784.  
  1785. void TCellsView::DoPostCreate(TDocument* itsDocument)
  1786. {
  1787.     fCalcDocument = (TCalcDocument *)(itsDocument);
  1788.     fHelpID = kCellsViewHelp;
  1789.     fHelpIndex = 1;
  1790. } // TCellsView::DoPostCreate 
  1791.  
  1792.  
  1793. //----------------------------------------------------------------------------------------
  1794. // TCellsView::DoMouseCommand: 
  1795. //----------------------------------------------------------------------------------------
  1796. #pragma segment ASelCommand
  1797.  
  1798. void TCellsView::DoMouseCommand(VPoint& theMouse,
  1799.                                 TToolboxEvent* event,
  1800.                                 CPoint /*hysteresis*/)    // override 
  1801. {
  1802.     TCalcSelectCommand * aCellSelector;
  1803.     TColumnSizer * aColumnSizer;
  1804.     GridCell aCell(-1, -1);
  1805.     GridViewPart whichPart;
  1806.     short aRow = -1;                            // This value should never be used
  1807.     short aCol = -1;                            // This value should never be used
  1808.     TGrabberTracker * aGrabber;
  1809.  
  1810.     whichPart = this->IdentifyPoint(theMouse, aCell);    //since almost ß
  1811.     aCol = aCell.h;
  1812.     aRow = aCell.v;
  1813.  
  1814.     if (event->IsOptionKeyPressed())
  1815.     {
  1816.         aGrabber = new TGrabberTracker;
  1817.         aGrabber->IGrabberTracker(cNoCommand, fCalcDocument, this, GetScroller(FALSE), theMouse);
  1818.         this->PostCommand(aGrabber);
  1819.     }
  1820.     else
  1821.     {
  1822.         switch (whichPart)
  1823.         {
  1824.             case inCell:
  1825.                 {
  1826.                     aCellSelector = new TCalcSelectCommand;
  1827.                     aCellSelector->ICalcSelectCommand(fCalcDocument, this, theMouse, event->IsShiftKeyPressed(), event->IsCommandKeyPressed());
  1828.                     this->PostCommand(aCellSelector);
  1829.                     fCalcDocument->fSelectionType = kCellSelection;
  1830.                     break;
  1831.                 }
  1832.  
  1833.             case inColumn:
  1834.             case inVertex:
  1835.                 {
  1836.                     if (aCol > 1)
  1837.                     {
  1838.                         aColumnSizer = new TColumnSizer;
  1839.                         aColumnSizer->IColumnSizer(fCalcDocument, aCol - 1, theMouse);
  1840.                         this->PostCommand(aColumnSizer);
  1841.                     }
  1842.                     break;
  1843.                 }
  1844.         }                                        // switch!!
  1845.         fCalcDocument->fColumnsView->SetEmptySelection(kHighlight);
  1846.         fCalcDocument->fRowsView->SetEmptySelection(kHighlight);
  1847.         fCalcDocument->fColumnIsSelected = FALSE;
  1848.         fCalcDocument->fEditCell = NULL;
  1849.     }
  1850. } // TCellsView::DoMouseCommand 
  1851.  
  1852.  
  1853. //----------------------------------------------------------------------------------------
  1854. // TCellsView::DoSetupMenus: 
  1855. //----------------------------------------------------------------------------------------
  1856. #pragma segment ARes
  1857.  
  1858. void TCellsView::DoSetupMenus()    // override 
  1859. {
  1860.     TypeOfSelection selection;
  1861.  
  1862.     Inherited::DoSetupMenus();
  1863.  
  1864.     // If user isn't editing, then assume edit commands refer to cells 
  1865.     if (!fCalcDocument->fEntryView->fTEditing)
  1866.     {
  1867.         SetEditCommandName(cCut, cCutCells);
  1868.         SetEditCommandName(cCopy, cCopyCells);
  1869.         SetEditCommandName(cClear, cClearCells);
  1870.  
  1871.         gClipboardMgr->CanPaste(kCalcScrapType);
  1872.     }
  1873.  
  1874.     selection = fCalcDocument->fSelectionType;
  1875.     Enable(cCut, selection != kNoSelection);
  1876.     Enable(cCopy, selection != kNoSelection);
  1877.     Enable(cClear, selection != kNoSelection);
  1878.     Enable(cSelectAll, TRUE);
  1879. } // TCellsView::DoSetupMenus 
  1880.  
  1881.  
  1882. //----------------------------------------------------------------------------------------
  1883. // TCellsView::DoMenuCommand: 
  1884. //----------------------------------------------------------------------------------------
  1885. #pragma segment ASelCommand
  1886.  
  1887. void TCellsView::DoMenuCommand(CommandNumber aCommandNumber)    // override 
  1888. {
  1889.     TCellEditCommand * aCellEditCommand;
  1890.     TCellPasteCommand * aCellPasteCommand;
  1891.     RgnHandle cellsToSelect;
  1892.     CRect aRect;
  1893.  
  1894.  
  1895.     switch (aCommandNumber)
  1896.     {
  1897.         case cSelectAll:
  1898.             {
  1899.                 aRect = fCalcDocument->fInUseBounds;
  1900.                 aRect.right++;
  1901.                 aRect.bottom++;
  1902.                 cellsToSelect = MakeNewRgn();
  1903.                 RectRgn(cellsToSelect, aRect);
  1904.                 this->SetSelection(cellsToSelect, kDontExtend, kHighlight, kSelect);
  1905.                 DisposeRgn(cellsToSelect);
  1906.                 fCalcDocument->fSelectionType = kAllSelection;
  1907.                 fCalcDocument->fRowsView->SetEmptySelection(kHighlight);
  1908.                 fCalcDocument->fColumnsView->SetEmptySelection(kHighlight);
  1909.                 fCalcDocument->fColumnIsSelected = FALSE;
  1910.                 break;
  1911.             }
  1912.  
  1913.         case cCut:
  1914.         case cCopy:
  1915.         case cClear:
  1916.             // If user isn't editing this cell, he must want the cell itself. 
  1917.             {
  1918.                 if (!fCalcDocument->fEntryView->fTEditing)
  1919.                 {
  1920.                     aCellEditCommand = new TCellEditCommand;
  1921.                     aCellEditCommand->ICellEditCommand(fCalcDocument, aCommandNumber);
  1922.                     this->PostCommand(aCellEditCommand);
  1923.                 }
  1924.                 else
  1925.                 {                                // get ready for TextEdit operation 
  1926.                     fCalcDocument->fEditCell = fCalcDocument->GetCell(fCalcDocument->fEditRow, fCalcDocument->fEditColumn);
  1927.                     Inherited::DoMenuCommand(aCommandNumber);
  1928.                 }
  1929.                 break;
  1930.             }
  1931.  
  1932.         case cPaste:
  1933.             {
  1934.                 if (gClipboardMgr->fClipView->ContainsClipType(kCalcScrapType))
  1935.                 {
  1936.                     aCellPasteCommand = new TCellPasteCommand;
  1937.                     aCellPasteCommand->ICellPasteCommand(fCalcDocument);
  1938.                     this->PostCommand(aCellPasteCommand);
  1939.                 }
  1940.                 else
  1941.                 {                                // paste text into entry view 
  1942.                     // was "WITH fCalcDocument"
  1943.                     fCalcDocument->fEditCell = fCalcDocument->GetCell(fCalcDocument->fEditRow, fCalcDocument->fEditColumn);
  1944.                     if (!fCalcDocument->fEntryView->fTEditing)
  1945.                         fCalcDocument->fEntryView->SetEditMode();// prepare view for paste of text 
  1946.  
  1947.                     Inherited::DoMenuCommand(aCommandNumber);
  1948.                 }
  1949.                 break;
  1950.             }
  1951.  
  1952.         default:
  1953.             Inherited::DoMenuCommand(aCommandNumber);
  1954.     }                                            // switch!!
  1955. } // TCellsView::DoMenuCommand 
  1956.  
  1957.  
  1958. //----------------------------------------------------------------------------------------
  1959. // TCellsView::DoKeyEvent: This view only handles arrow keys, tab, return and enter. It
  1960. // assumes the other keys are handled by the entry view object.
  1961. //----------------------------------------------------------------------------------------
  1962. #pragma segment ARes
  1963.  
  1964. void TCellsView::DoKeyEvent(TToolboxEvent* event)
  1965. {
  1966.     ColumnNumber c = fCalcDocument->fEditColumn;
  1967.     RowNumber r = fCalcDocument->fEditRow;
  1968.  
  1969.     Boolean handled = TRUE;
  1970.  
  1971.     if (event->fText == chEnter)
  1972.         fCalcDocument->SetChangeCount(Max(fCalcDocument->fChangeCount + 1, 1));// enable Save - document may have changed Stay on same cell 
  1973.     else if (event->fText == chTab || event->fText == chRight)
  1974.         c = Min(c + 1, fCalcDocument->fNoOfColumns);
  1975.     else if (event->fText == chLeft)
  1976.         c = Max(c - 1, (short)1);
  1977.     else if (event->fText == chUp)
  1978.         r = Max(r - 1, (short)1);
  1979.     else if (event->fText == chReturn || event->fText == chDown)
  1980.     {
  1981.         if (r)    // only do this if a cell is selected
  1982.             r = Min(r + 1, fCalcDocument->fNoOfRows);
  1983.     }
  1984.     else
  1985.         handled = FALSE;
  1986.  
  1987.     if (handled)
  1988.     {
  1989.         GridCell aCell(c, r);
  1990.     
  1991.         //  used to be one HUGE "with fCalcDocument" 
  1992.         //-- why is the view messing so much with the doc's internals?????
  1993.     
  1994.         fCalcDocument->fEntryView->EditMode(FALSE);
  1995.         fCalcDocument->fColumnsView->SetEmptySelection(kHighlight);
  1996.         fCalcDocument->fRowsView->SetEmptySelection(kHighlight);
  1997.         fCalcDocument->fColumnIsSelected = FALSE;
  1998.     
  1999.         SelectCell(aCell, kDontExtend, kHighlight, kSelect);
  2000.         if (fCalcDocument->fEntryView->fTouched)
  2001.             fCalcDocument->DoRecalculate(!kForceAutomatic, kUpdateDependencies);
  2002.         ScrollSelectionIntoView(TRUE);
  2003.     
  2004.         // fix the columns view 
  2005.         VPoint minToSee(fCalcDocument->fColumnsView->GetColWidth(aCell.h), kCellHeight);
  2006.         aCell.v = 1;
  2007.     
  2008.         fCalcDocument->fColumnsView->RevealRect(fCalcDocument->fColumnsView->CellToVRect(aCell), minToSee, TRUE);
  2009.     
  2010.         // fix the rows view 
  2011.         minToSee.h = kCellWidth;
  2012.         minToSee.v = kCellHeight;
  2013.         aCell.v = r;
  2014.         aCell.h = 1;
  2015.         fCalcDocument->fRowsView->RevealRect(fCalcDocument->fRowsView->CellToVRect(aCell), minToSee, TRUE);
  2016.     
  2017.         // redraw anything that has changed, so the user can see what's being scrolled to
  2018.         Update();
  2019.     }
  2020.     else
  2021.     {
  2022.         Inherited::DoKeyEvent(event);
  2023.         fCalcDocument->fEditCell = fCalcDocument->GetCell(r, c);
  2024.     }
  2025. } // TCellsView::DoKeyEvent 
  2026.  
  2027.  
  2028. //----------------------------------------------------------------------------------------
  2029. // TCellsView::AdornCol: 
  2030. //----------------------------------------------------------------------------------------
  2031. #pragma segment ARes
  2032.  
  2033. void TCellsView::AdornCol(short /*aCol*/, const VRect& area)    // override 
  2034. {
  2035.     PenPat(&gColumnSeparatorPattern);
  2036.     PenSize(1, 1);
  2037.  
  2038.     CRect qdArea(ViewToQDRect(area));
  2039.     MoveTo(qdArea.right - 1, qdArea.top);
  2040.     LineToPt(qdArea[botRight] - CPoint(1, 1));
  2041. } // TCellsView::AdornCol 
  2042.  
  2043.  
  2044. //----------------------------------------------------------------------------------------
  2045. // TCellsView::AdornRow: 
  2046. //----------------------------------------------------------------------------------------
  2047. #pragma segment ARes
  2048.  
  2049. void TCellsView::AdornRow(short /*aCol*/, const VRect& area)    // override 
  2050. {
  2051.     PenPat(&gRowSeparatorPattern);
  2052.     PenSize(1, 1);
  2053.  
  2054.     CRect qdArea(ViewToQDRect(area));
  2055.     MoveTo(qdArea.left, qdArea.bottom - 1);
  2056.     LineToPt(qdArea[botRight] - CPoint(1, 1));
  2057. } // TCellsView::AdornRow 
  2058.  
  2059.  
  2060. //----------------------------------------------------------------------------------------
  2061. // TCellsView::DesignatorAsTEXT: 
  2062. //----------------------------------------------------------------------------------------
  2063. #pragma segment GNonRes2
  2064.  
  2065. Handle TCellsView::DesignatorAsTEXT(TDesignator* aDesignator)
  2066. {
  2067.     CRect bounds;
  2068.     Handle textHandle;
  2069.     THandleStream * aHandleStream;
  2070.     CStr255 theString;
  2071.     RgnHandle aRgn;
  2072.  
  2073.     textHandle = NewPermHandle(100);
  2074.     aHandleStream = new THandleStream;
  2075.     aHandleStream->IHandleStream(textHandle, 10);
  2076.     aRgn = ((TRegionDesignator *)(aDesignator))->fDesignation;
  2077.     bounds = (*aRgn)->rgnBBox;
  2078.     bounds.bottom--;
  2079.     bounds.right--;
  2080.     CCellIterator iter(this, bounds[topLeft], bounds[botRight], kIterateForward, kIterateForward, CCellIterator::kIterateRowMajor);
  2081.     for (GridCell aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  2082.     {
  2083.         SignedByte aChar;
  2084.  
  2085.  
  2086.         // write out the cell's contents if the cell is in the designation && it exists 
  2087.         if (PtInRgn(aCell, aRgn) && fCalcDocument->CellExists(aCell.v, aCell.h))
  2088.         {
  2089.             fCalcDocument->GetCell(aCell.v, aCell.h)->GetValueAsString(theString);
  2090.             aHandleStream->WriteBytes(&theString[1], theString.Length());// we can't use WriteString
  2091.             // because it writes the
  2092.             // length byte as well
  2093.         }
  2094.  
  2095.         // write out the delimitter - tab or cr 
  2096.         if (aCell.h == bounds.right)
  2097.             aChar = 0x0D;
  2098.         else
  2099.             aChar = 0x09;
  2100.         aHandleStream->WriteBytes(&aChar, sizeof(SignedByte));
  2101.     }
  2102.     aHandleStream->Free();
  2103.     return textHandle;
  2104. } // TCellsView::DesignatorAsTEXT 
  2105.  
  2106.  
  2107. //----------------------------------------------------------------------------------------
  2108. // TCellsView::DoIdle: 
  2109. //----------------------------------------------------------------------------------------
  2110. #pragma segment ARes
  2111.  
  2112. Boolean TCellsView::DoIdle(IdlePhase /* phase */)
  2113. {
  2114.     KeyMap aKeyMap;
  2115.  
  2116.     GetKeys(aKeyMap);
  2117.     if (fLastOptionKey != IsOptionKeyDown())
  2118.     {
  2119.         fLastOptionKey = IsOptionKeyDown();
  2120.         gApplication->InvalidateCursorRgn();    // Since we track the option key, we now need  
  2121.                                                 // to recalculate cursor rgn and SET the
  2122.                                                 // cursor at next opportunity
  2123.     }
  2124.     return FALSE;                                // Didn't free myself 
  2125. } // TCellsView::DoIdle 
  2126.  
  2127.  
  2128. //----------------------------------------------------------------------------------------
  2129. // TCellsView::DoSetCursor: 
  2130. //----------------------------------------------------------------------------------------
  2131. #pragma segment ARes
  2132.  
  2133. void TCellsView::DoSetCursor(const VPoint& globalMouse,
  2134.                              RgnHandle cursorRegion)    // override 
  2135. {
  2136.     KeyMap aKeyMap;
  2137.     GetKeys(aKeyMap);
  2138.  
  2139.     // We may have been called from a mouse-moved.  Be kind to the DoIdle 
  2140.     fLastOptionKey = IsOptionKeyDown();
  2141.  
  2142.     if (fLastOptionKey)
  2143.     {
  2144.         SetCursor(*GetCursor(kGrabberHand));
  2145.         RectRgn(cursorRegion, &this->GetQDExtent());
  2146.     }
  2147.     else
  2148.     {
  2149.         VRect cellsExtent;
  2150.         short aRow = -1;                            // This value should never be used
  2151.         short aCol = -1;                            // This value should never be used
  2152.     
  2153.  
  2154.         GridCell aCell(-1, -1);                        // This value should never be used
  2155.         GridViewPart aGridViewPart = this->IdentifyPoint(globalMouse, aCell);
  2156.         aCol = aCell.h;
  2157.         aRow = aCell.v;
  2158.  
  2159.         switch (aGridViewPart)                    //since almost ß
  2160.         {
  2161.             case badChoice:
  2162.                 break;
  2163.  
  2164.             case inColumn:
  2165.             case inVertex:
  2166.                 {
  2167.                     if (aCol > 1)
  2168.                     {
  2169.                         SetCursor(*GetCursor(kColumnSizingCursor));
  2170.                         this->ColToVRect(Min(aCol, fNumOfCols), 1, cellsExtent);
  2171.                         CRect columnQDExtent(this->ViewToQDRect(cellsExtent));
  2172.  
  2173.                         // Which edge is the mouse closer to? 
  2174.                         if (labs(columnQDExtent.right - globalMouse.h) < labs(columnQDExtent.left - globalMouse.h))
  2175.                             columnQDExtent.left = columnQDExtent.right;
  2176.  
  2177.                         columnQDExtent.left = columnQDExtent.left - fColInset / 2;
  2178.                         columnQDExtent.right = columnQDExtent.left + fColInset;
  2179.                         RectRgn(cursorRegion, columnQDExtent);
  2180.                     }
  2181.                     break;
  2182.                 }
  2183.             case inRow:
  2184.             case inCell:
  2185.                 {
  2186.                     SetCursor(*GetCursor(plusCursor));
  2187.                     this->ColToVRect(Min(aCol, fNumOfCols), 1, cellsExtent);
  2188.                     cellsExtent.Inset(VPoint(fColInset / 2, 0));// Account for the column resizer 
  2189.                     RectRgn(cursorRegion, &this->ViewToQDRect(cellsExtent));
  2190.                     break;
  2191.                 }
  2192.         }                                        // switch
  2193.     }
  2194. } // TCellsView::DoSetCursor 
  2195.  
  2196.  
  2197. //----------------------------------------------------------------------------------------
  2198. // TCellsView::DrawCell: 
  2199. //----------------------------------------------------------------------------------------
  2200. #pragma segment ARes
  2201.  
  2202. void TCellsView::DrawCell(GridCell aCell, const VRect& aRect)    // override 
  2203. {
  2204.     TCell * theCell = fCalcDocument->GetExistingCell(aCell.v, aCell.h);
  2205.     if ((theCell != NULL) &&!theCell->fDeleted)
  2206.     {
  2207.         CStr255 theString;
  2208.         theCell->GetValueAsString(theString);
  2209.         SmartDrawString(theString, this->ViewToQDRect(aRect), fCalcDocument->GetColumn(aCell.h)->fFormat.fJustification);
  2210.     }
  2211. } // TCellsView::DrawCell 
  2212.  
  2213.  
  2214. //----------------------------------------------------------------------------------------
  2215. // TCellsView::GetVisibleCells: 
  2216. //----------------------------------------------------------------------------------------
  2217. #pragma segment ADoCommand
  2218.  
  2219. CRect TCellsView::GetVisibleCells()
  2220. {
  2221.     this->Focus();
  2222.     VRect visibleVRect(GetVisibleRect());
  2223.     visibleVRect[topLeft] = GetScroller(TRUE)->fTranslation;
  2224.  
  2225.     return CRect(VPointToCell(visibleVRect[topLeft]), VPointToCell(visibleVRect[botRight]));
  2226. } // TCellsView::GetVisibleCells 
  2227.  
  2228.  
  2229. //----------------------------------------------------------------------------------------
  2230. // TCellsView::IsCellVisible: 
  2231. //----------------------------------------------------------------------------------------
  2232. #pragma segment ADoCommand
  2233.  
  2234. Boolean TCellsView::IsCellVisible(GridCell aCell)
  2235. {
  2236.     return GetVisibleCells().Contains(aCell);        // ??? use fCalcDocument.CellInRange 
  2237. } // TCellsView::IsCellVisible 
  2238.  
  2239.  
  2240. //----------------------------------------------------------------------------------------
  2241. // TCellsView::PositionAtCell: 
  2242. //----------------------------------------------------------------------------------------
  2243. #pragma segment ADoCommand
  2244.  
  2245. void TCellsView::PositionAtCell(GridCell aCell)
  2246. {
  2247.     // position the cells view first 
  2248.     VRect aRect(CellToVRect(aCell));
  2249.     VPoint minToSee(aRect.right - aRect.left, aRect.bottom - aRect.top);
  2250.     RevealRect(aRect, minToSee, TRUE);
  2251.  
  2252.     // fix up the columns view 
  2253.     short r = aCell.v;
  2254.     minToSee.h = fCalcDocument->fColumnsView->GetColWidth(aCell.h);
  2255.     minToSee.v = kCellHeight;
  2256.     aCell.v = 1;
  2257.     fCalcDocument->fColumnsView->CellToVRect(aCell, aRect);
  2258.     fCalcDocument->fColumnsView->RevealRect(aRect, minToSee, TRUE);
  2259.  
  2260.     // fix up the rows view 
  2261.     minToSee.h = kCellWidth;
  2262.     minToSee.v = kCellHeight;
  2263.     aCell.v = r;
  2264.     aCell.h = 1;
  2265.     fCalcDocument->fRowsView->CellToVRect(aCell, aRect);
  2266.     fCalcDocument->fRowsView->RevealRect(aRect, minToSee, TRUE);
  2267. } // TCellsView::PositionAtCell 
  2268.  
  2269.  
  2270. //----------------------------------------------------------------------------------------
  2271. // TCellsView::ReSelect: 
  2272. //----------------------------------------------------------------------------------------
  2273. #pragma segment ADoCommand
  2274.  
  2275. void TCellsView::ReSelect(RgnHandle cellRegion)
  2276. {
  2277.     GridCell aCell;
  2278.     CRect rgnBBox = (*cellRegion)->rgnBBox;
  2279.  
  2280.     aCell = rgnBBox[topLeft];
  2281.     if (!this->IsCellVisible(aCell))
  2282.         this->PositionAtCell(aCell);            // position cellRegion at top left of grid 
  2283.  
  2284.     if (!EqualRect(rgnBBox, &((*fSelections)->rgnBBox)))
  2285.     {
  2286.         fCalcDocument->fColumnsView->SetEmptySelection(kHighlight);
  2287.         fCalcDocument->fRowsView->SetEmptySelection(kHighlight);
  2288.         fCalcDocument->fColumnIsSelected = FALSE;
  2289.         this->SetSelection(cellRegion, kDontExtend, kHighlight, kSelect);
  2290.     }
  2291. } // TCellsView::ReSelect 
  2292.  
  2293.  
  2294. //----------------------------------------------------------------------------------------
  2295. // TCellsView::ReSelectCell: 
  2296. //----------------------------------------------------------------------------------------
  2297. #pragma segment ADoCommand
  2298.  
  2299. void TCellsView::ReSelectCell(GridCell aCell)
  2300. {
  2301.     CRect cellRect;
  2302.  
  2303.     if (!this->IsCellVisible(aCell))
  2304.         this->PositionAtCell(aCell);            // position aCell at top left of grid 
  2305.  
  2306.     SetRect(cellRect, aCell.h, aCell.v, aCell.h + 1, aCell.v + 1);
  2307.     if (!EqualRect(cellRect, &((*fSelections)->rgnBBox)))
  2308.     {
  2309.         fCalcDocument->fColumnsView->SetEmptySelection(kHighlight);
  2310.         fCalcDocument->fRowsView->SetEmptySelection(kHighlight);
  2311.         fCalcDocument->fColumnIsSelected = FALSE;
  2312.         this->SelectCell(aCell, kDontExtend, kHighlight, kSelect);
  2313.     }
  2314. } // TCellsView::ReSelectCell 
  2315.  
  2316.  
  2317. //----------------------------------------------------------------------------------------
  2318. // TCellsView::ScrollSelectionIntoView: 
  2319. //----------------------------------------------------------------------------------------
  2320. #pragma segment ADoCommand
  2321.  
  2322. void TCellsView::ScrollSelectionIntoView(Boolean redraw)    // override 
  2323. {
  2324.     if (!(EmptyRgn(fSelections)))
  2325.     {    VRect topLeftRect(CellToVRect(((CRect &)(*fSelections)->rgnBBox)[topLeft]));
  2326.         RevealRect(topLeftRect, topLeftRect.GetSize(), redraw);
  2327.     }
  2328. } // TCellsView::ScrollSelectionIntoView 
  2329.  
  2330. //----------------------------------------------------------------------------------------
  2331. // TCellsView::SetCell: 
  2332. //----------------------------------------------------------------------------------------
  2333. #pragma segment ADoCommand
  2334.  
  2335. void TCellsView::SetCell(GridCell aCell)
  2336. {
  2337.     fCalcDocument->EditCell();                    // cell formula = CString in entry view 
  2338.     this->InvalidateCell(aCell);                // redraw the cell 
  2339. } // TCellsView::SetCell 
  2340.  
  2341.  
  2342. //----------------------------------------------------------------------------------------
  2343. // TCellsView::SetColWidth: 
  2344. //----------------------------------------------------------------------------------------
  2345. #pragma segment ADoCommand
  2346.  
  2347. void TCellsView::SetColWidth(short aCol,
  2348.                              short numOfCols,
  2349.                              short aWidth)    // override 
  2350. {
  2351.     Inherited::SetColWidth(aCol, numOfCols, aWidth);
  2352.  
  2353.     {
  2354.         // notify the cells that the width was changed 
  2355.         CExistingCalcCellIterator iter(fCalcDocument);
  2356.         for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  2357.             if (aCell->fColumn == aCol)
  2358.                 aCell->Changed(mWidthChanged, this);
  2359.     }
  2360.     // recompute the border rgns 
  2361.     {
  2362.         CAdornerIterator iter(this);
  2363.  
  2364.         for (TAdorner * anAdorner = iter.FirstAdorner(); iter.More(); anAdorner = iter.NextAdorner())
  2365.         {
  2366.             TSectionAdorner * aSectionAdorner;
  2367.  
  2368.             if ((anAdorner != NULL) && anAdorner->DescendsFrom(TSectionAdorner::GetClassDescStatic()))
  2369.             {
  2370.                 aSectionAdorner = (TSectionAdorner *)(anAdorner);
  2371.                 this->ComputeBorderRgn(aSectionAdorner->fBorderRegion, ((TRegionDesignator *)(aSectionAdorner->fSection)->fDesignator)->fDesignation);
  2372.             }
  2373.         }
  2374.     }
  2375. } // TCellsView::SetColWidth 
  2376.  
  2377.  
  2378. //----------------------------------------------------------------------------------------
  2379. // TCellsView::SetSelection: 
  2380. //----------------------------------------------------------------------------------------
  2381. #pragma segment ADoCommand
  2382.  
  2383. void TCellsView::SetSelection(RgnHandle cellsToSelect,
  2384.                               Boolean extendSelection,
  2385.                               Boolean highlight,
  2386.                               Boolean select)    // Override 
  2387. {
  2388.     CRect aQDRect;
  2389.  
  2390.     Inherited::SetSelection(cellsToSelect, extendSelection, highlight, select);
  2391.  
  2392.     if (fCalcDocument->fEntryView->fTouched)    // "commit" last cell 
  2393.     {
  2394.         fCalcDocument->EditCell();                /* change fEditCell's formula to the CString
  2395.                                                   in fEntryView */
  2396.         fCalcDocument->fEntryView->SetToString(gEmptyString);
  2397.     }
  2398.  
  2399.     CRect    boundRect;
  2400.     CPoint    onePt(1,1);
  2401.     
  2402.     boundRect = (*cellsToSelect)->rgnBBox;
  2403.     if (!extendSelection && (boundRect.GetSize() == onePt))
  2404.     {
  2405.         CPoint cellTopLeft = ((CRect &)(*cellsToSelect)->rgnBBox)[topLeft];
  2406.  
  2407.         fCalcDocument->fEditColumn = cellTopLeft.h;
  2408.         fCalcDocument->fEditRow = cellTopLeft.v;
  2409.         fCalcDocument->fEditCell = fCalcDocument->fCells->GetCell(fCalcDocument->fEditRow, fCalcDocument->fEditColumn);
  2410.  
  2411.         fCalcDocument->fCoordView->ForceRedraw();
  2412.         fCalcDocument->fEntryView->SetEnable(TRUE);    // Allow editing.
  2413.     }
  2414.     else
  2415.         if (!extendSelection)
  2416.         {
  2417.             if (boundRect.GetLength(hSel) == 1)
  2418.                 fCalcDocument->fEditColumn = boundRect.left;
  2419.             else
  2420.                 fCalcDocument->fEditColumn = 0;
  2421.  
  2422.             if (boundRect.GetLength(vSel) == 1)    
  2423.                 fCalcDocument->fEditRow = boundRect.top;
  2424.             else
  2425.                 fCalcDocument->fEditRow = 0;
  2426.  
  2427.             fCalcDocument->fEditCell = NULL;
  2428.  
  2429.             fCalcDocument->fCoordView->ForceRedraw();
  2430.             fCalcDocument->fEntryView->SetEnable(FALSE);    // Don't allow editing of thin air.
  2431.         }
  2432.  
  2433.     fCalcDocument->SetEntry(fCalcDocument->fEditRow, fCalcDocument->fEditColumn);// set entry view contents to new cell 
  2434. } // TCellsView::SetSelection 
  2435.  
  2436.  
  2437. //----------------------------------------------------------------------------------------
  2438. // TCellsView::DoBreakFollowing: 
  2439. //----------------------------------------------------------------------------------------
  2440. #pragma segment GNonRes2
  2441.  
  2442. // Determines where page breaks occur for printing. 
  2443. VCoordinate TCellsView::DoBreakFollowing(VHSelect vhs,
  2444.                                          VCoordinate previousBreak,
  2445.                                          Boolean& /*Automatic*/)    // override 
  2446. {
  2447.     VCoordinate thisBreak = 0;
  2448.     short rowsPerPage;
  2449.     short totalWidth;
  2450.     short width;
  2451.     short pageWidth;
  2452.     ColumnNumber firstCol;
  2453.     ColumnNumber c;
  2454.  
  2455.     VRect extentRect(GetExtent());
  2456.     switch (vhs)
  2457.     {
  2458.         case hSel:
  2459.             {
  2460.                 rowsPerPage = (short)(GetPrintHandler()->GetViewPerPage().v / kCellHeight);
  2461.                 thisBreak = previousBreak + (rowsPerPage * kCellHeight);
  2462.                 break;
  2463.             }
  2464.         case vSel:
  2465.             {
  2466.                 pageWidth = (short)GetPrintHandler()->GetViewPerPage().h;
  2467.                 totalWidth = 0;
  2468.                 // This section used to be "firstCol = ColumnAtCoord(previousBreak);"
  2469.                 if (previousBreak == 0)
  2470.                     firstCol = 1;
  2471.                 else
  2472.                 {
  2473.                     c = 0;
  2474.                     width = 0;
  2475.                     do
  2476.                     {
  2477.                         ++c;
  2478.                         width = width + GetColWidth(c);
  2479.                     } while (width < previousBreak);
  2480.                     firstCol = c + 1;
  2481.                 }
  2482.                 for (c = firstCol; c <= fCalcDocument->fNoOfColumns; c++)
  2483.                 {
  2484.                     width = this->GetColWidth(c);
  2485.                     if (totalWidth + width <= pageWidth)
  2486.                         totalWidth += width;
  2487.                     else
  2488.                     {
  2489.                         thisBreak = previousBreak + totalWidth;
  2490.                         break;
  2491.                     }
  2492.                 }
  2493.                 
  2494.                 // Did we set it?
  2495.                 if (thisBreak == 0)
  2496.                     thisBreak = previousBreak + totalWidth;
  2497.                     
  2498.                 if (thisBreak == previousBreak)    // Prevent ∞ loop resizing a far-right column (L.T.!)
  2499.                     thisBreak = extentRect.right;
  2500.                 break;
  2501.             }
  2502.     }
  2503.     thisBreak = Min(thisBreak, extentRect[botRight][gOrthogonal[vhs]]);
  2504.  
  2505. #if qDebug
  2506.     if ((thisBreak <= previousBreak) || gDebugPrinting)
  2507.     {
  2508.         fprintf(stderr, "TCellsView.DoBreakFollowing: previousBreak=");
  2509.         if (vhs == vSel)
  2510.             fprintf(stderr, "[v]%d  thisBreak=[v]%d\n", previousBreak, thisBreak);
  2511.         else
  2512.             fprintf(stderr, "[h]%d  thisBreak=[h]%d\n", previousBreak, thisBreak);
  2513.  
  2514.         if (thisBreak <= previousBreak)
  2515.             ProgramBreak("thisBreak <= previousBreak");
  2516.     }
  2517. #endif
  2518.  
  2519.     return thisBreak;
  2520. } // TCellsView::DoBreakFollowing 
  2521.  
  2522.  
  2523. //----------------------------------------------------------------------------------------
  2524. // TCellsView::DoDrawPageBreak: 
  2525. //----------------------------------------------------------------------------------------
  2526. #if qDebug
  2527. #pragma segment GNonRes2
  2528.  
  2529. void TCellsView::DoDrawPageBreak(VHSelect vhs,
  2530.                                  short /*whichBreak*/,
  2531.                                  VCoordinate loc,
  2532.                                  Boolean /*Automatic*/)    // override 
  2533. {
  2534.     VPoint vPt;
  2535.     CPoint qdStartPt;
  2536.     CPoint qdEndPt;
  2537.  
  2538.     if (gDebugPrinting)
  2539.     {
  2540.         vPt[gOrthogonal[vhs]] = loc;
  2541.         vPt[vhs] = 0;
  2542.         qdStartPt = ViewToQDPt(vPt);
  2543.         vPt[vhs] = fSize[vhs] - ((CPoint &)gBreaksPenState.pnSize)[vhs];
  2544.         qdEndPt = ViewToQDPt(vPt);
  2545.  
  2546.         MoveToPt(qdStartPt);
  2547.         LineToPt(qdEndPt);
  2548.     }
  2549. } // TCellsView::DoDrawPageBreak 
  2550.  
  2551. #endif
  2552.  
  2553. //----------------------------------------------------------------------------------------
  2554. // TCellsView::GetPrintExtent:  Overridden to provide for Print Selection command. 
  2555. //----------------------------------------------------------------------------------------
  2556. #pragma segment GNonRes2
  2557.  
  2558. VRect TCellsView::GetPrintExtent()    // override 
  2559. {
  2560.     VRect printExtent;
  2561.     GridCell tlCell;
  2562.     GridCell brCell;
  2563.  
  2564.     if (((TCalcPrintHandler *)(GetPrintHandler()))->fCmdNumber == cPrintSelection)
  2565.     {
  2566.         tlCell = ((CRect &)(*fSelections)->rgnBBox)[topLeft];
  2567.         brCell = ((CRect &)(*fSelections)->rgnBBox)[botRight];
  2568.         brCell.h = Min(brCell.h - 1, fCalcDocument->fInUseBounds.right);
  2569.         brCell.v = Min(brCell.v - 1, fCalcDocument->fInUseBounds.bottom);
  2570.     }
  2571.     else
  2572.     {
  2573.         tlCell = fCalcDocument->fInUseBounds[topLeft];
  2574.         brCell = fCalcDocument->fInUseBounds[botRight];
  2575.     }
  2576.  
  2577.     VRect aRect(CellToVRect(tlCell));
  2578.     printExtent[topLeft] = aRect[topLeft];
  2579.     this->CellToVRect(brCell, aRect);
  2580.     printExtent[botRight] = aRect[botRight];
  2581.  
  2582. #if qDebug
  2583.     if (gDebugPrinting)
  2584.     {
  2585.         fprintf(stderr, "printExtent %s\n", (const char*)printExtent);
  2586.     }
  2587. #endif
  2588.  
  2589.     return printExtent;
  2590. } // TCellsView::GetPrintExtent 
  2591.  
  2592. //----------------------------------------------------------------------------------------
  2593. // TCellsView::UserSelectionChanged: 
  2594. //----------------------------------------------------------------------------------------
  2595. #pragma segment MAViewRes
  2596.  
  2597. void TCellsView::UserSelectionChanged(TView* changedView)
  2598. {
  2599.     if (!fCalcDocument->fShowSectionBorders)
  2600.     {
  2601.         // invalidate all adorners
  2602.         CAdornerIterator iter(this);
  2603.         
  2604.         for (TAdorner* theAdorner = iter.FirstAdorner(); iter.More(); theAdorner = iter.NextAdorner())
  2605.         {
  2606.             if ((theAdorner->fIdentifier == kPublisherAdornerID)
  2607.                 || (theAdorner->fIdentifier == kSubscriberAdornerID))
  2608.             {
  2609.                 theAdorner->InvalidateAdorner(this);
  2610.             }
  2611.         }
  2612.     }
  2613.  
  2614.     Inherited::UserSelectionChanged(changedView);
  2615. } // TCellsView::UserSelectionChanged 
  2616.  
  2617. //----------------------------------------------------------------------------------------
  2618. // TCellsView::ContainsClipType: 
  2619. //----------------------------------------------------------------------------------------
  2620. #pragma segment AClipBoard
  2621.  
  2622. Boolean TCellsView::ContainsClipType(ResType aType)
  2623. {
  2624.     return (aType == kCalcScrapType);
  2625. } // TCellsView::ContainsClipType 
  2626.  
  2627.  
  2628. //----------------------------------------------------------------------------------------
  2629. // TCellsView::WriteCalcScrap: 
  2630. //----------------------------------------------------------------------------------------
  2631. #pragma segment AClipBoard
  2632.  
  2633. void TCellsView::WriteCalcScrap(Handle calcScrap)
  2634. {
  2635.     long scrapOffset;
  2636.     ScrapInfoRecord scrapInfo;
  2637.     short cellsWritten;
  2638.     short i;
  2639.     CRect r;
  2640.  
  2641.     SetHandleSize(calcScrap, 0);
  2642.     scrapOffset = 0;
  2643.  
  2644.     scrapInfo.selection.top = 1;
  2645.     scrapInfo.selection.left = 1;
  2646.     scrapInfo.selection.bottom = fCalcDocument->fNoOfRows;
  2647.     scrapInfo.selection.right = fCalcDocument->fNoOfColumns;
  2648.     scrapInfo.noOfCells = fCalcDocument->fAllocatedCells;
  2649.     WriteScrap(calcScrap, scrapOffset, (unsigned char*) & scrapInfo, sizeof(scrapInfo));
  2650.  
  2651.     cellsWritten = 0;
  2652.  
  2653.     for (i = 1; i <= fCalcDocument->fNoOfRows; i++)
  2654.     {
  2655.         fCalcDocument->GetRow(i)->WriteToScrap(calcScrap, scrapOffset);
  2656.     }
  2657.  
  2658.     for (i = 1; i <= fCalcDocument->fNoOfColumns; i++)
  2659.     {
  2660.         fCalcDocument->GetColumn(i)->WriteToScrap(calcScrap, scrapOffset);
  2661.     }
  2662.  
  2663.     CExistingCalcCellIterator iter(fCalcDocument);
  2664.     for (TCell * aCell = iter.FirstCell(); iter.More(); aCell = iter.NextCell())
  2665.     {
  2666.         aCell->WriteToScrap(calcScrap, scrapOffset);
  2667.         cellsWritten = cellsWritten + 1;
  2668.     }                                            // EachExistingCellDo(WriteCellToScrap);
  2669.  
  2670. #if qDebug
  2671.     fprintf(stderr, "WriteCalcScrap: Number of cells written:%d\n", cellsWritten);
  2672.     if (cellsWritten != scrapInfo.noOfCells)
  2673.     {
  2674.         fprintf(stderr, "WriteCalcScrap: Incorrect number of cells written.\n");
  2675.         fprintf(stderr, "     Should be %d , was %d\n", scrapInfo.noOfCells, cellsWritten);
  2676.         ProgramBreak("");
  2677.     }
  2678. #endif
  2679.  
  2680. } // TCellsView::WriteCalcScrap 
  2681.  
  2682.  
  2683. //----------------------------------------------------------------------------------------
  2684. // TCellsView::WriteTextScrap: 
  2685. //----------------------------------------------------------------------------------------
  2686. #pragma segment AClipBoard
  2687.  
  2688. void TCellsView::WriteTextScrap(Handle textScrap)
  2689. {
  2690.     RowNumber r;
  2691.     ColumnNumber c;
  2692.     CStr255 theText;
  2693.     CStr255 tabString = CStr255("\t");
  2694.     CStr255 returnString = CStr255("\n");
  2695.     long scrapOffset;
  2696.     GrafPtr savedPort;
  2697.  
  2698.     GetPort(&savedPort);                            // Use work port because GetValueAsString 
  2699.     SetPort(gWorkPort);                            // …sets the current port's font 
  2700.  
  2701.     SetHandleSize(textScrap, 0);
  2702.     scrapOffset = 0;
  2703.  
  2704.     for (r = 1; r <= fCalcDocument->fNoOfRows; r++)
  2705.     {
  2706.         for (c = 1; c <= fCalcDocument->fNoOfColumns; c++)
  2707.         {
  2708.             if (fCalcDocument->CellExists(r, c))
  2709.                 fCalcDocument->GetCell(r, c)->GetValueAsString(theText);
  2710.             else
  2711.                 theText.Empty();
  2712.             if (c > 1)
  2713.                 theText = tabString + theText;
  2714.             WriteScrap(textScrap, scrapOffset, &(theText.fStr[1]), theText.Length());
  2715.             //WriteString(theText);
  2716.         }
  2717.         theText = returnString;
  2718.         WriteScrap(textScrap, scrapOffset, &(theText.fStr[1]), theText.Length());
  2719.         //WriteString(theText);
  2720.     }
  2721.  
  2722.     SetPort(savedPort);
  2723. } // TCellsView::WriteTextScrap 
  2724.  
  2725.  
  2726. //----------------------------------------------------------------------------------------
  2727. // TCellsView::WriteToDeskScrap: 
  2728. //----------------------------------------------------------------------------------------
  2729. #pragma segment AClipBoard
  2730.  
  2731. void TCellsView::WriteToDeskScrap()        // override 
  2732. {
  2733.     Handle textScrap;
  2734.     Handle calcScrap;
  2735.     OSErr err;
  2736.  
  2737.     textScrap = NewPermHandle(0);
  2738.     this->WriteTextScrap(textScrap);
  2739.     err = gClipboardMgr->PutDeskScrapData(kTextScrapType, textScrap);
  2740.     textScrap = DisposeIfHandle(textScrap);
  2741.  
  2742.     FailOSErr(err);
  2743.  
  2744.     calcScrap = NewPermHandle(0);
  2745.     this->WriteCalcScrap(calcScrap);
  2746.     err = gClipboardMgr->PutDeskScrapData(kCalcScrapType, calcScrap);
  2747.     calcScrap = DisposeIfHandle(calcScrap);
  2748.  
  2749.     FailOSErr(err);
  2750. } // TCellsView::WriteToDeskScrap 
  2751.  
  2752.  
  2753. //========================================================================================
  2754. // CLASS TCalcPrintHandler
  2755. //========================================================================================
  2756. #undef Inherited
  2757. #define Inherited TStdPrintHandler
  2758.  
  2759. #pragma segment ClassDescRes
  2760. MA_DEFINE_CLASS_M1(TCalcPrintHandler, Inherited);
  2761.  
  2762. //----------------------------------------------------------------------------------------
  2763. // TCalcPrintHandler destructor
  2764. //----------------------------------------------------------------------------------------
  2765. #pragma segment MADestructorRes
  2766.  
  2767. TCalcPrintHandler::~TCalcPrintHandler()
  2768. {
  2769. }
  2770.  
  2771. //----------------------------------------------------------------------------------------
  2772. // TCalcPrintHandler::CalcViewPerPage: 
  2773. //----------------------------------------------------------------------------------------
  2774. #pragma segment PrintNonRes
  2775.  
  2776. VPoint TCalcPrintHandler::CalcViewPerPage()    // override 
  2777. {
  2778.     VPoint amtPerPage(Inherited::CalcViewPerPage());
  2779.     
  2780.     long noOfRows = amtPerPage.v / kCellHeight;
  2781.     amtPerPage.v = noOfRows * kCellHeight;
  2782.     
  2783.     return amtPerPage;
  2784. } // TCalcPrintHandler::CalcViewPerPage 
  2785.  
  2786.  
  2787. //----------------------------------------------------------------------------------------
  2788. // TCalcPrintHandler::DoMenuCommand: 
  2789. //----------------------------------------------------------------------------------------
  2790. #pragma segment PrintRes
  2791.  
  2792. void TCalcPrintHandler::DoMenuCommand(CommandNumber aCommandNumber)    // override 
  2793. {
  2794.     fCmdNumber = aCommandNumber;                // Save command number for GetPrintExtent 
  2795.     if (aCommandNumber == cPrintSelection)
  2796.         aCommandNumber = cPrint;                // proceed like regular Print 
  2797.     Inherited::DoMenuCommand(aCommandNumber);
  2798. } // TCalcPrintHandler::DoMenuCommand 
  2799.  
  2800.  
  2801. //----------------------------------------------------------------------------------------
  2802. // TCalcPrintHandler::DoSetupMenus: 
  2803. //----------------------------------------------------------------------------------------
  2804. #pragma segment PrintRes
  2805.  
  2806. void TCalcPrintHandler::DoSetupMenus()    // override 
  2807. {
  2808.     Inherited::DoSetupMenus();
  2809.     Enable(cPrintSelection, gCouldPrint && (fView != NULL));
  2810. } // TCalcPrintHandler::DoSetupMenus 
  2811.  
  2812.  
  2813. //========================================================================================
  2814. // CLASS TEntryView
  2815. //========================================================================================
  2816. #undef Inherited
  2817. #define Inherited TTEView
  2818.  
  2819. #pragma segment ClassDescRes
  2820. MA_DEFINE_CLASS_M1(TEntryView, Inherited);
  2821.  
  2822. //----------------------------------------------------------------------------------------
  2823. // TEntryView destructor
  2824. //----------------------------------------------------------------------------------------
  2825. #pragma segment MADestructorRes
  2826.  
  2827. TEntryView::~TEntryView()
  2828. {
  2829. }
  2830.  
  2831. //----------------------------------------------------------------------------------------
  2832. // TEntryView::DoPostCreate: 
  2833. //----------------------------------------------------------------------------------------
  2834. #pragma segment AOpen
  2835.  
  2836. void TEntryView::DoPostCreate(TDocument* itsDocument)
  2837. {
  2838.     fDocument = itsDocument;
  2839.     fCalcDocument = (TCalcDocument *)(itsDocument);
  2840.     fTouched = FALSE;
  2841.     fTEditing = FALSE;
  2842.     fFirstEdit = FALSE;
  2843.     fOldString.Empty();
  2844.  
  2845.     fControlChars = macroAsSetElem(chBackspace);    // The others are handled by the cells view
  2846. } // TEntryView::DoPostCreate 
  2847.  
  2848.  
  2849. //----------------------------------------------------------------------------------------
  2850. // TEntryView::DoKeyEvent: 
  2851. //----------------------------------------------------------------------------------------
  2852. #pragma segment ARes
  2853.  
  2854. void TEntryView::DoKeyEvent(TToolboxEvent* event)    // override 
  2855. {
  2856.     // If this is the first character, wipe out old value and activate caret. 
  2857.     if ((!fTEditing) && ((event->fText >= chSpace) || (event->fText == chBackspace)))
  2858.         SetEditMode();
  2859.  
  2860.     Inherited::DoKeyEvent(event);
  2861. } // TEntryView::DoKeyEvent 
  2862.  
  2863.  
  2864. //----------------------------------------------------------------------------------------
  2865. // TEntryView::DoMakeTypingCommand: 
  2866. //----------------------------------------------------------------------------------------
  2867. #pragma segment ASelCommand
  2868.  
  2869. TTETypingCommand* TEntryView::DoMakeTypingCommand(const CStr2& ch)    // override 
  2870. {
  2871.     TCalcTypingCommand* aTypingCommand = new TCalcTypingCommand;
  2872.     aTypingCommand->ICalcTypingCommand(this, ch);
  2873.     return aTypingCommand;
  2874. } // TEntryView::DoMakeTypingCommand 
  2875.  
  2876.  
  2877. //----------------------------------------------------------------------------------------
  2878. // TEntryView::DoMouseCommand: 
  2879. //----------------------------------------------------------------------------------------
  2880. #pragma segment ASelCommand
  2881.  
  2882. void TEntryView::DoMouseCommand(VPoint& theMouse,
  2883.                                 TToolboxEvent* event,
  2884.                                 CPoint hysteresis)    // override 
  2885. {
  2886.     // If no characters typed, active caret, then handle mouse down. 
  2887.     if (!fTouched)
  2888.     {
  2889.         this->SetActive(TRUE);
  2890.         fTouched = TRUE;
  2891.     }
  2892.     this->EditMode(TRUE);
  2893.     Inherited::DoMouseCommand(theMouse, event, hysteresis);
  2894. } // TEntryView::DoMouseCommand 
  2895.  
  2896.  
  2897. //----------------------------------------------------------------------------------------
  2898. // TEntryView::DoMenuCommand: 
  2899. //----------------------------------------------------------------------------------------
  2900. #pragma segment TESelCommand
  2901.  
  2902. void TEntryView::DoMenuCommand(CommandNumber aCommandNumber)
  2903. {
  2904.     if (fTEditing)
  2905.     {
  2906.         // TTEView.DoMenuCommand will process the Cut/ Paste/ Clear for us, but we only want
  2907.         // it to if we're editing in the first place. Otherwise, we can't call inherited,
  2908.         // because then CPC commands we recieve should go to the CellsView, so therefore
  2909.         // we just tell the next handler to do its thing, thus continuing the chain (see
  2910.         // TEventHandler::DoMenuCommand)
  2911.  
  2912.         Inherited::DoMenuCommand(aCommandNumber);
  2913.     }
  2914.     else
  2915.     {
  2916.         TEventHandler* nextHandler = this->GetNextHandler();
  2917.         if (nextHandler)
  2918.             nextHandler->HandleMenuCommand(aCommandNumber);
  2919.     }
  2920. } // TEntryView::DoMenuCommand 
  2921.  
  2922.  
  2923. //----------------------------------------------------------------------------------------
  2924. // TEntryView::DoSetupMenus: 
  2925. //----------------------------------------------------------------------------------------
  2926. #pragma segment ARes
  2927.  
  2928. void TEntryView::DoSetupMenus()            // override 
  2929. {
  2930.     if (fTEditing)
  2931.     {
  2932.         // TTEView.DoSetupMenus will setup the Edit menu commands for us if we're editing.
  2933.         // But if we're not, we can't call inherited, because then they'll still get set
  2934.         // up. To give somebody else the chance to setup, we'll just move onto the next
  2935.         // handler (see TEventHandler::DoSetupMenus )
  2936.         Inherited::DoSetupMenus();
  2937.  
  2938.         SetEditCommandName(cCut, cCutText);
  2939.         SetEditCommandName(cCopy, cCopyText);
  2940.         SetEditCommandName(cClear, cClearText);
  2941.     }
  2942.     else
  2943.     {
  2944.         TEventHandler* nextHandler = this->GetNextHandler();
  2945.         if (nextHandler)
  2946.             nextHandler->HandleSetupMenus();
  2947.     }
  2948. } // TEntryView::DoSetupMenus 
  2949.  
  2950.  
  2951. //----------------------------------------------------------------------------------------
  2952. // TEntryView::SetupUndoMenu: 
  2953. //----------------------------------------------------------------------------------------
  2954. //    #pragma segment ARes
  2955.  
  2956. //    void TEntryView::SetupUndoMenu()            // override 
  2957. //    {
  2958. //        if (fTEditing)
  2959. //        {
  2960. //            // TTEView.SetupUndoMenu will handle setting the undo for us, but we only want it to
  2961. //            // if we're editing in the first place.  Otherwise, we can't call inherited, because then
  2962. //            // CPC commands we recieve should go to the CellsView, so therefore we just tell the next
  2963. //            // handler to do its thing, thus continuing the chain (see TEventHandler::DoMenuCommand)
  2964. //    
  2965. //            Inherited::SetupUndoMenu();
  2966. //        }
  2967. //    } // TEntryView::SetupUndoMenu 
  2968.  
  2969.  
  2970. //----------------------------------------------------------------------------------------
  2971. // TEntryView::Draw: 
  2972. //----------------------------------------------------------------------------------------
  2973. #pragma segment ARes
  2974.  
  2975. void TEntryView::Draw(const VRect& area)    // override 
  2976. {
  2977.     Inherited::Draw(area);
  2978.  
  2979.     // We want a rectangle around the whole view 
  2980.     PenSize(1, 1);
  2981.     PenPat(&qd.black);
  2982.     FrameRect(&GetQDExtent());
  2983.  
  2984.     Inherited::Draw(area);
  2985. } // TEntryView::Draw 
  2986.  
  2987.  
  2988. //----------------------------------------------------------------------------------------
  2989. // TEntryView::WantsToBeTarget: 
  2990. //----------------------------------------------------------------------------------------
  2991. #pragma segment ARes
  2992.  
  2993. Boolean TEntryView::WantsToBeTarget()    // override 
  2994. {
  2995.     // Return false for now, because Calc currently relies on the cells view being the target
  2996.     return FALSE;
  2997. } // TEntryView::WantsToBeTarget 
  2998.  
  2999.  
  3000.  
  3001. //----------------------------------------------------------------------------------------
  3002. // TEntryView::EditMode: 
  3003. //----------------------------------------------------------------------------------------
  3004. #pragma segment ASelCommand
  3005.  
  3006. void TEntryView::EditMode(Boolean editing)
  3007. {
  3008.     fTEditing = editing;
  3009.     fFirstEdit = FALSE;                            // set to true only by DoKeyEvent 
  3010.  
  3011.     if (editing)
  3012.         GetAsString(fOldString);                // save previous CString for Undo/Redo 
  3013.  
  3014.     //    else
  3015.     //    {
  3016.     //        // disable undo/redo for TTECommands. ???
  3017.     //        // There must be a better way! this is
  3018.     //        // disgusting!
  3019.     //        TCommand* lastCommand = this->GetLastCommand();
  3020.     //        if (lastCommand != NULL)
  3021.     //            if (lastCommand->GetClassDescDynamic()->GetBaseClass() == TTECommand::GetClassDescStatic())
  3022.     //                lastCommand->fCanUndo = FALSE;
  3023.     //
  3024.     //    }
  3025. } // TEntryView::EditMode 
  3026.  
  3027.  
  3028. //----------------------------------------------------------------------------------------
  3029. // TEntryView::GetAsString: 
  3030. //----------------------------------------------------------------------------------------
  3031. #pragma segment ARes
  3032.  
  3033. void TEntryView::GetAsString(CStr255& theString)
  3034. {
  3035.     CharsHandle theText = (CharsHandle)(this->ExtractText());
  3036.     short numberOfChars = (short)Min(255, GetHandleSize(Handle(theText)));
  3037.     theString.CopyFrom((void*)*theText, Min(255, numberOfChars));
  3038. } // TEntryView::GetAsString 
  3039.  
  3040.  
  3041. //----------------------------------------------------------------------------------------
  3042. // TEntryView::SetActive: 
  3043. //----------------------------------------------------------------------------------------
  3044. #pragma segment ARes
  3045.  
  3046. void TEntryView::SetActive(Boolean state)// Override 
  3047. {
  3048.     Inherited::SetActive(state);
  3049.  
  3050.     if (Focus())
  3051.     {
  3052.         CRect r;
  3053.         this->GetQDExtent(r);
  3054.         InsetRect(r, 2, 2);
  3055.         this->InvalidateRect(r);
  3056.     }
  3057. } // TEntryView::SetActive 
  3058.  
  3059.  
  3060. //----------------------------------------------------------------------------------------
  3061. // TEntryView::SetEditMode: 
  3062. //----------------------------------------------------------------------------------------
  3063. #pragma segment ASelCommand
  3064.  
  3065. void TEntryView::SetEditMode()
  3066. {
  3067.     this->EditMode(TRUE);                        // sets fFirstEdit to false 
  3068.     fFirstEdit = TRUE;                            // the only place it is set to true 
  3069.     SetToString(gEmptyString);
  3070.     this->SetActive(TRUE);
  3071.     fTouched = TRUE;
  3072. } // TEntryView::SetEditMode 
  3073.  
  3074.  
  3075. //----------------------------------------------------------------------------------------
  3076. // TEntryView::SetToString: 
  3077. //----------------------------------------------------------------------------------------
  3078. #pragma segment ARes
  3079.  
  3080. void TEntryView::SetToString(const CStr255& theString)
  3081. {
  3082.     CStr255 tempString = theString;
  3083.  
  3084.     this->Focus();
  3085.     SetJustification(teFlushDefault, kDontRedraw);// initialize text to system-justified 
  3086.     this->SetActive(FALSE);
  3087.     fTouched = FALSE;
  3088.     TESetText(&((CStr255 &)tempString)[1], tempString.Length(), fHTE);
  3089.     // first cast away the const so that the [] operator returns a reference to
  3090.     // the actual location in the array (otherwise returns the character itself
  3091.     // on the stack) since we're interested in an address, not what it contains,
  3092.     // then actually do the [] operator to get the start of the CString to stuff.
  3093.     TESetSelect(0, 32768, fHTE);                // hilight the entire CString.
  3094. } // TEntryView::SetToString 
  3095.  
  3096.  
  3097. //----------------------------------------------------------------------------------------
  3098. // TEntryView::SwapStrings: 
  3099. //----------------------------------------------------------------------------------------
  3100. #pragma segment ADoCommand
  3101.  
  3102. void TEntryView::SwapStrings()
  3103. {
  3104.     CStr255 newString;
  3105.  
  3106.     newString = fOldString;
  3107.     GetAsString(fOldString);
  3108.     SetToString(newString);
  3109.     fTouched = TRUE;
  3110. } // TEntryView::SwapStrings 
  3111.  
  3112.  
  3113. //========================================================================================
  3114. // CLASS TCoordView
  3115. //========================================================================================
  3116. #undef Inherited
  3117. #define Inherited TView
  3118.  
  3119. #pragma segment ClassDescRes
  3120. MA_DEFINE_CLASS_M1(TCoordView, Inherited);
  3121.  
  3122. //----------------------------------------------------------------------------------------
  3123. // TCoordView destructor
  3124. //----------------------------------------------------------------------------------------
  3125. #pragma segment MADestructorRes
  3126.  
  3127. TCoordView::~TCoordView()
  3128. {
  3129. }
  3130.  
  3131. //----------------------------------------------------------------------------------------
  3132. // TCoordView::DoPostCreate: 
  3133. //----------------------------------------------------------------------------------------
  3134. #pragma segment AOpen
  3135.  
  3136. void TCoordView::DoPostCreate(TDocument* itsDocument)
  3137. {
  3138.     fCalcDocument = (TCalcDocument *)(itsDocument);
  3139. } // TCoordView::DoPostCreate 
  3140.  
  3141.  
  3142. //----------------------------------------------------------------------------------------
  3143. // TCoordView::Draw: 
  3144. //----------------------------------------------------------------------------------------
  3145. #pragma segment ARes
  3146.  
  3147. void TCoordView::Draw(const VRect& area)
  3148. {
  3149.     CStr255 aString;
  3150.     CStr255 anotherString;
  3151.     CRect aRect;
  3152.  
  3153.     if (fCalcDocument->fEditColumn > 0)
  3154.         fCalcDocument->fColumnsView->CoordToString(fCalcDocument->fEditColumn, aString);
  3155.     else
  3156.         aString = " ";
  3157.  
  3158.     if (fCalcDocument->fEditRow > 0)
  3159.         NumToString(fCalcDocument->fEditRow, anotherString);
  3160.     else
  3161.         anotherString = " ";
  3162.  
  3163.     aString = aString + anotherString;
  3164.     SetTheFont(kEntryFont, kEntryFontSize, bold);
  3165.     SetRect(aRect, 2, 0, 46, kEntryHeight);
  3166.     SmartDrawString(aString, aRect, teFlushDefault);
  3167.  
  3168.     Inherited::Draw(area);
  3169. } // TCoordView::Draw 
  3170.  
  3171.  
  3172. //========================================================================================
  3173. // CLASS TCalcSelectCommand
  3174. //========================================================================================
  3175. #undef Inherited
  3176. #define Inherited TCellSelectCommand
  3177.  
  3178. #pragma segment ClassDescRes
  3179. MA_DEFINE_CLASS_M1(TCalcSelectCommand, Inherited);
  3180.  
  3181. //----------------------------------------------------------------------------------------
  3182. // TCalcSelectCommand destructor
  3183. //----------------------------------------------------------------------------------------
  3184. #pragma segment MADestructorRes
  3185.  
  3186. TCalcSelectCommand::~TCalcSelectCommand()
  3187. {
  3188. }
  3189.  
  3190. //----------------------------------------------------------------------------------------
  3191. // TCalcSelectCommand::ICalcSelectCommand: 
  3192. //----------------------------------------------------------------------------------------
  3193. #pragma segment ASelCommand
  3194.  
  3195. void TCalcSelectCommand::ICalcSelectCommand(TCalcDocument* itsDocument,
  3196.                                             TGridView* itsView,
  3197.                                             VPoint& theMouse,
  3198.                                             Boolean theShiftKey,
  3199.                                             Boolean theCommandKey)
  3200. {
  3201.     this->ICellSelectCommand(itsView, theMouse, theShiftKey, theCommandKey);
  3202.     fCalcDocument = itsDocument;
  3203.     itsDocument->fEntryView->EditMode(FALSE);
  3204. } // TCalcSelectCommand::ICalcSelectCommand 
  3205.  
  3206.  
  3207. //----------------------------------------------------------------------------------------
  3208. // TCalcSelectCommand::ComputeNewSelection: 
  3209. //----------------------------------------------------------------------------------------
  3210. #pragma segment ADoCommand
  3211.  
  3212. void TCalcSelectCommand::ComputeNewSelection(GridCell& clickedCell)    // override 
  3213. {
  3214.     CRect r;
  3215.  
  3216.     if (fGridView->CanSelectCell(clickedCell))
  3217.     {
  3218.         Pt2Rect(fAnchorCell, clickedCell, r);
  3219.         ++r.right;
  3220.         ++r.bottom;
  3221.         RectRgn(fThisSelection, r);
  3222.  
  3223.         // add in the designated region for subscribers 
  3224. #if qDebug
  3225.         UseTemporaryRegion("TCalcSelectCommand.ComputeNewSelection");
  3226. #endif
  3227.  
  3228.         CSectionIterator iter(fCalcDocument);    // for each section do
  3229.         for (TSection * aSection = iter.FirstSection(); iter.More(); aSection = iter.NextSection())
  3230.         {
  3231.             if (!aSection->IsCanceled() && aSection->GetSectionType() == stSubscriber)
  3232.             {
  3233.                 SectRgn(fThisSelection, ((TRegionDesignator *)(aSection->fDesignator))->fDesignation, gTemporaryRegion);
  3234.                 if (!EmptyRgn(gTemporaryRegion))// if this section is in selection 
  3235.                     UnionRgn(fThisSelection, ((TRegionDesignator *)(aSection->fDesignator))->fDesignation, fThisSelection);
  3236.             }
  3237.         }                                        // THIS WAS fCalcDocument->EachSectionDo(DoToSection);
  3238. #if qDebug
  3239.         DoneWithTemporaryRegion();
  3240. #endif
  3241.  
  3242.         if (fCommandKey && (!fGridView->fSingleSelection))
  3243.             if (fDeselecting)
  3244.                 DiffRgn(fPreviousSelection, fThisSelection, fThisSelection);
  3245.             else
  3246.                 UnionRgn(fPreviousSelection, fThisSelection, fThisSelection);
  3247.     }
  3248. } // TCalcSelectCommand::ComputeNewSelection 
  3249.  
  3250.  
  3251.  
  3252. //========================================================================================
  3253. // CLASS TCalcTypingCommand
  3254. //========================================================================================
  3255. #undef Inherited
  3256. #define Inherited TTETypingCommand
  3257.  
  3258. #pragma segment ClassDescRes
  3259. MA_DEFINE_CLASS_M1(TCalcTypingCommand, Inherited);
  3260.  
  3261. //----------------------------------------------------------------------------------------
  3262. // TCalcTypingCommand destructor
  3263. //----------------------------------------------------------------------------------------
  3264. #pragma segment MADestructorRes
  3265.  
  3266. TCalcTypingCommand::~TCalcTypingCommand()
  3267. {
  3268. }
  3269.  
  3270. //----------------------------------------------------------------------------------------
  3271. // TCalcTypingCommand::ICalcTypingCommand: 
  3272. //----------------------------------------------------------------------------------------
  3273. #pragma segment ADoCommand
  3274.  
  3275. void TCalcTypingCommand::ICalcTypingCommand(TTEView* itsTEView,
  3276.                                             const CStr2& itsFirstChar)    // override 
  3277. {
  3278.     Inherited::ITETypingCommand(itsTEView, itsFirstChar);
  3279.     fCellsView = ((TEntryView *)(itsTEView))->fCalcDocument->fCellsView;
  3280.     fTargetCell = fCellsView->FirstSelectedCell();
  3281. } // TCalcTypingCommand::ICalcTypingCommand 
  3282.  
  3283.  
  3284. //----------------------------------------------------------------------------------------
  3285. // TCalcTypingCommand::AddCharacter: Switch the entry view from left to right
  3286. // justification when the typed characters overflow the entry box, and switch back to left
  3287. // justification if the text shrinks enough
  3288. //----------------------------------------------------------------------------------------
  3289. #pragma segment ARes
  3290.  
  3291. void TCalcTypingCommand::AddCharacter(const CStr2& ch)// override 
  3292. {
  3293.     if ((ch != chBackspace) && (fTEView->fJustification == teFlushDefault))
  3294.     {
  3295.         short selRight = (*fHTE)->selRect.right;
  3296.         if ((selRight < 0) || (selRight > (*fHTE)->destRect.right))
  3297.             selRight = (*fHTE)->selPoint.h;
  3298.         if ((selRight + StringWidth(ch) > (*fHTE)->destRect.right))
  3299.             fTEView->SetJustification(teFlushRight, kDontRedraw);
  3300.     }
  3301.  
  3302.     Inherited::AddCharacter(ch);
  3303.  
  3304.     if ((ch == chBackspace) && (fTEView->fJustification == teFlushRight))
  3305.     {
  3306.         CStr255 aString;
  3307.  
  3308.         GetDialogItemText((*fHTE)->hText, aString);
  3309.         if (StringWidth(aString) < LengthRect((*fHTE)->destRect, hSel))
  3310.             fTEView->SetJustification(teFlushDefault, kRedraw);
  3311.     }
  3312. } // TCalcTypingCommand::AddCharacter 
  3313.  
  3314.  
  3315. //----------------------------------------------------------------------------------------
  3316. // TCalcTypingCommand::UndoIt: If the selection has changed since this command was
  3317. // created, restore it to the target cell before Undoing.
  3318. //----------------------------------------------------------------------------------------
  3319. #pragma segment ADoCommand
  3320.  
  3321. void TCalcTypingCommand::UndoIt()        // override 
  3322. {
  3323.     fCellsView->ReSelectCell(fTargetCell);        // make sure fTargetCell is selected 
  3324.     TEntryView * entryView = (TEntryView *)(fTEView);
  3325.     if ((entryView->fTEditing) && (!entryView->fFirstEdit))
  3326.         Inherited::UndoIt();                    // TTE undo 
  3327.     else
  3328.     {
  3329.         entryView->SwapStrings();                // exchange current and saved strings 
  3330.         fCellsView->SetCell(fTargetCell);        // change fTargetCell's contents and redraw it
  3331.     }
  3332. } // TCalcTypingCommand::UndoIt 
  3333.  
  3334.  
  3335. //----------------------------------------------------------------------------------------
  3336. // TCalcTypingCommand::RedoIt: If the selection has changed since this command was
  3337. // created, restore it to the target cell before Redoing.
  3338. //----------------------------------------------------------------------------------------
  3339. #pragma segment ADoCommand
  3340.  
  3341. void TCalcTypingCommand::RedoIt()        // override 
  3342. {
  3343.     fCellsView->ReSelectCell(fTargetCell);        // make sure fTargetCell is selected 
  3344.     TEntryView * entryView = (TEntryView *)(fTEView);
  3345.     if ((entryView->fTEditing) && (!entryView->fFirstEdit))
  3346.         Inherited::RedoIt();                    // TTE redo 
  3347.     else
  3348.     {
  3349.         entryView->SwapStrings();                // exchange current and saved strings 
  3350.         fCellsView->SetCell(fTargetCell);        // change fTargetCell's contents and redraw it
  3351.     }
  3352. } // TCalcTypingCommand::RedoIt 
  3353.  
  3354. //----------------------------------------------------------------------------------------
  3355. // End of UCalc.cp
  3356.  
  3357. #pragma segment Inline
  3358.